40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.h"
44#include "llvm/ADT/SetVector.h"
45#include "llvm/ADT/SmallSet.h"
46#include "llvm/ADT/StringExtras.h"
47#include "llvm/Frontend/OpenMP/OMPAssume.h"
48#include "llvm/Frontend/OpenMP/OMPConstants.h"
49#include "llvm/IR/Assumptions.h"
53using namespace llvm::omp;
68enum DefaultDataSharingAttributes {
73 DSA_firstprivate = 1 << 3,
80enum DefaultDataSharingVCAttributes {
94 unsigned Modifier = 0;
95 const Expr *RefExpr =
nullptr;
96 DeclRefExpr *PrivateCopy =
nullptr;
97 SourceLocation ImplicitDSALoc;
98 bool AppliedToPointee =
false;
99 DSAVarData() =
default;
101 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
102 SourceLocation ImplicitDSALoc,
unsigned Modifier,
103 bool AppliedToPointee)
104 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
105 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
106 AppliedToPointee(AppliedToPointee) {}
108 using OperatorOffsetTy =
109 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
110 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
112 enum class UsesAllocatorsDeclKind {
116 UserDefinedAllocator,
124 unsigned Modifier = 0;
127 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
128 DeclRefExpr *PrivateCopy =
nullptr;
131 bool AppliedToPointee =
false;
133 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
134 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
135 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
136 using LoopControlVariablesMapTy =
137 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
140 struct MappedExprComponentTy {
144 using MappedExprComponentsTy =
145 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
146 using CriticalsWithHintsTy =
147 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
148 struct ReductionData {
149 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
150 SourceRange ReductionRange;
151 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
152 ReductionData() =
default;
157 void set(
const Expr *RefExpr, SourceRange RR) {
159 ReductionOp = RefExpr;
162 using DeclReductionMapTy =
163 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
164 struct DefaultmapInfo {
168 DefaultmapInfo() =
default;
170 : ImplicitBehavior(M), SLoc(Loc) {}
173 struct SharingMapTy {
174 DeclSAMapTy SharingMap;
175 DeclReductionMapTy ReductionMap;
176 UsedRefMapTy AlignedMap;
177 UsedRefMapTy NontemporalMap;
178 MappedExprComponentsTy MappedExprComponents;
179 LoopControlVariablesMapTy LCVMap;
180 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
181 SourceLocation DefaultAttrLoc;
182 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
183 SourceLocation DefaultAttrVCLoc;
186 DeclarationNameInfo DirectiveName;
187 Scope *CurScope =
nullptr;
188 DeclContext *Context =
nullptr;
189 SourceLocation ConstructLoc;
193 DoacrossClauseMapTy DoacrossDepends;
197 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
198 bool RegionHasOrderConcurrent =
false;
199 unsigned AssociatedLoops = 1;
200 bool HasMutipleLoops =
false;
201 const Decl *PossiblyLoopCounter =
nullptr;
202 bool NowaitRegion =
false;
203 bool UntiedRegion =
false;
204 bool CancelRegion =
false;
205 bool LoopStart =
false;
206 bool BodyComplete =
false;
207 SourceLocation PrevScanLocation;
208 SourceLocation PrevOrderedLocation;
209 SourceLocation InnerTeamsRegionLoc;
211 Expr *TaskgroupReductionRef =
nullptr;
212 llvm::DenseSet<QualType> MappedClassesQualTypes;
213 SmallVector<Expr *, 4> InnerUsedAllocators;
214 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
217 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
219 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
220 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
224 struct ImplicitDefaultFDInfoTy {
226 const FieldDecl *FD =
nullptr;
228 size_t StackLevel = 0;
230 VarDecl *VD =
nullptr;
231 ImplicitDefaultFDInfoTy(
const FieldDecl *FD,
size_t StackLevel,
233 : FD(FD), StackLevel(StackLevel), VD(VD) {}
236 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
237 ImplicitDefaultFirstprivateFDs;
238 Expr *DeclareMapperVar =
nullptr;
239 SmallVector<VarDecl *, 16> IteratorVarDecls;
241 Scope *CurScope, SourceLocation Loc)
242 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
244 SharingMapTy() =
default;
247 using StackTy = SmallVector<SharingMapTy, 4>;
250 DeclSAMapTy Threadprivates;
251 DeclSAMapTy Groupprivates;
252 const FunctionScopeInfo *CurrentNonCapturingFunctionScope =
nullptr;
253 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
258 bool ForceCapturing =
false;
261 bool ForceCaptureByReferenceInTargetExecutable =
false;
262 CriticalsWithHintsTy Criticals;
263 unsigned IgnoredStackElements = 0;
267 using const_iterator = StackTy::const_reverse_iterator;
268 const_iterator begin()
const {
269 return Stack.empty() ? const_iterator()
270 : Stack.back().first.rbegin() + IgnoredStackElements;
272 const_iterator end()
const {
273 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
275 using iterator = StackTy::reverse_iterator;
277 return Stack.empty() ? iterator()
278 : Stack.back().first.rbegin() + IgnoredStackElements;
281 return Stack.empty() ? iterator() : Stack.back().first.rend();
286 bool isStackEmpty()
const {
287 return Stack.empty() ||
288 Stack.back().second != CurrentNonCapturingFunctionScope ||
289 Stack.back().first.size() <= IgnoredStackElements;
291 size_t getStackSize()
const {
292 return isStackEmpty() ? 0
293 : Stack.back().first.size() - IgnoredStackElements;
296 SharingMapTy *getTopOfStackOrNull() {
297 size_t Size = getStackSize();
300 return &Stack.back().first[
Size - 1];
302 const SharingMapTy *getTopOfStackOrNull()
const {
303 return const_cast<DSAStackTy &
>(*this).getTopOfStackOrNull();
305 SharingMapTy &getTopOfStack() {
306 assert(!isStackEmpty() &&
"no current directive");
307 return *getTopOfStackOrNull();
309 const SharingMapTy &getTopOfStack()
const {
310 return const_cast<DSAStackTy &
>(*this).getTopOfStack();
313 SharingMapTy *getSecondOnStackOrNull() {
314 size_t Size = getStackSize();
317 return &Stack.back().first[
Size - 2];
319 const SharingMapTy *getSecondOnStackOrNull()
const {
320 return const_cast<DSAStackTy &
>(*this).getSecondOnStackOrNull();
329 SharingMapTy &getStackElemAtLevel(
unsigned Level) {
330 assert(
Level < getStackSize() &&
"no such stack element");
331 return Stack.back().first[
Level];
333 const SharingMapTy &getStackElemAtLevel(
unsigned Level)
const {
334 return const_cast<DSAStackTy &
>(*this).getStackElemAtLevel(
Level);
337 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D)
const;
340 bool isOpenMPLocal(VarDecl *D, const_iterator Iter)
const;
343 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
345 QualType OMPAllocatorHandleT;
349 QualType OMPEventHandleT;
351 QualType OMPAlloctraitT;
353 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
356 SmallVector<SourceLocation, 2> TargetLocations;
357 SourceLocation AtomicLocation;
359 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
362 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
365 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
367 QualType getOMPAllocatorHandleT()
const {
return OMPAllocatorHandleT; }
369 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
371 QualType getOMPAlloctraitT()
const {
return OMPAlloctraitT; }
373 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
375 OMPPredefinedAllocators[AllocatorKind] = Allocator;
378 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind)
const {
379 return OMPPredefinedAllocators[AllocatorKind];
382 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
384 QualType getOMPDependT()
const {
return OMPDependT; }
387 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
389 QualType getOMPEventHandleT()
const {
return OMPEventHandleT; }
391 bool isClauseParsingMode()
const {
return ClauseKindMode != OMPC_unknown; }
393 assert(isClauseParsingMode() &&
"Must be in clause parsing mode.");
394 return ClauseKindMode;
398 bool isBodyComplete()
const {
399 const SharingMapTy *Top = getTopOfStackOrNull();
400 return Top && Top->BodyComplete;
402 void setBodyComplete() { getTopOfStack().BodyComplete =
true; }
404 bool isForceVarCapturing()
const {
return ForceCapturing; }
405 void setForceVarCapturing(
bool V) { ForceCapturing =
V; }
407 void setForceCaptureByReferenceInTargetExecutable(
bool V) {
408 ForceCaptureByReferenceInTargetExecutable =
V;
410 bool isForceCaptureByReferenceInTargetExecutable()
const {
411 return ForceCaptureByReferenceInTargetExecutable;
415 Scope *CurScope, SourceLocation Loc) {
416 assert(!IgnoredStackElements &&
417 "cannot change stack while ignoring elements");
419 Stack.back().second != CurrentNonCapturingFunctionScope)
420 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
421 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
422 Stack.back().first.back().DefaultAttrLoc = Loc;
426 assert(!IgnoredStackElements &&
427 "cannot change stack while ignoring elements");
428 assert(!Stack.back().first.empty() &&
429 "Data-sharing attributes stack is empty!");
430 Stack.back().first.pop_back();
435 class ParentDirectiveScope {
440 ParentDirectiveScope(DSAStackTy &Self,
bool Activate)
441 : Self(Self), Active(
false) {
445 ~ParentDirectiveScope() { disable(); }
448 --Self.IgnoredStackElements;
454 ++Self.IgnoredStackElements;
463 "Expected loop-based directive.");
464 getTopOfStack().LoopStart =
true;
469 "Expected loop-based directive.");
470 getTopOfStack().LoopStart =
false;
473 bool isLoopStarted()
const {
475 "Expected loop-based directive.");
476 return !getTopOfStack().LoopStart;
479 void resetPossibleLoopCounter(
const Decl *D =
nullptr) {
480 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
483 const Decl *getPossiblyLoopCounter()
const {
484 return getTopOfStack().PossiblyLoopCounter;
487 void pushFunction() {
488 assert(!IgnoredStackElements &&
489 "cannot change stack while ignoring elements");
490 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
492 CurrentNonCapturingFunctionScope = CurFnScope;
495 void popFunction(
const FunctionScopeInfo *OldFSI) {
496 assert(!IgnoredStackElements &&
497 "cannot change stack while ignoring elements");
498 if (!Stack.empty() && Stack.back().second == OldFSI) {
499 assert(Stack.back().first.empty());
502 CurrentNonCapturingFunctionScope =
nullptr;
503 for (
const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
505 CurrentNonCapturingFunctionScope = FSI;
511 void addCriticalWithHint(
const OMPCriticalDirective *D, llvm::APSInt Hint) {
512 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
514 std::pair<const OMPCriticalDirective *, llvm::APSInt>
515 getCriticalWithHint(
const DeclarationNameInfo &Name)
const {
517 if (I != Criticals.end())
519 return std::make_pair(
nullptr, llvm::APSInt());
524 const Expr *addUniqueAligned(
const ValueDecl *D,
const Expr *NewDE);
528 const Expr *addUniqueNontemporal(
const ValueDecl *D,
const Expr *NewDE);
531 void addLoopControlVariable(
const ValueDecl *D, VarDecl *
Capture);
536 const LCDeclInfo isLoopControlVariable(
const ValueDecl *D)
const;
541 const LCDeclInfo isParentLoopControlVariable(
const ValueDecl *D)
const;
546 const LCDeclInfo isLoopControlVariable(
const ValueDecl *D,
547 unsigned Level)
const;
550 const ValueDecl *getParentLoopControlVariable(
unsigned I)
const;
553 void markDeclAsUsedInScanDirective(ValueDecl *D) {
554 if (SharingMapTy *Stack = getSecondOnStackOrNull())
555 Stack->UsedInScanDirective.insert(D);
559 bool isUsedInScanDirective(ValueDecl *D)
const {
560 if (
const SharingMapTy *Stack = getTopOfStackOrNull())
561 return Stack->UsedInScanDirective.contains(D);
567 DeclRefExpr *PrivateCopy =
nullptr,
unsigned Modifier = 0,
568 bool AppliedToPointee =
false);
572 void addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
576 void addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
577 const Expr *ReductionRef);
581 getTopMostTaskgroupReductionData(
const ValueDecl *D, SourceRange &SR,
583 Expr *&TaskgroupDescriptor)
const;
587 getTopMostTaskgroupReductionData(
const ValueDecl *D, SourceRange &SR,
588 const Expr *&ReductionRef,
589 Expr *&TaskgroupDescriptor)
const;
592 Expr *getTaskgroupReductionRef()
const {
593 assert((getTopOfStack().
Directive == OMPD_taskgroup ||
597 "taskgroup reference expression requested for non taskgroup or "
598 "parallel/worksharing directive.");
599 return getTopOfStack().TaskgroupReductionRef;
603 bool isTaskgroupReductionRef(
const ValueDecl *VD,
unsigned Level)
const {
604 return getStackElemAtLevel(
Level).TaskgroupReductionRef &&
611 const DSAVarData getTopDSA(ValueDecl *D,
bool FromParent);
613 const DSAVarData getImplicitDSA(ValueDecl *D,
bool FromParent)
const;
615 const DSAVarData getImplicitDSA(ValueDecl *D,
unsigned Level)
const;
622 DefaultDataSharingAttributes)>
625 bool FromParent)
const;
630 hasInnermostDSA(ValueDecl *D,
633 bool FromParent)
const;
638 hasExplicitDSA(
const ValueDecl *D,
640 unsigned Level,
bool NotLastprivate =
false)
const;
644 bool hasExplicitDirective(
646 unsigned Level)
const;
650 const llvm::function_ref<
bool(
653 bool FromParent)
const;
657 const SharingMapTy *Top = getTopOfStackOrNull();
658 return Top ? Top->Directive : OMPD_unknown;
662 assert(!isStackEmpty() &&
"No directive at specified level.");
663 return getStackElemAtLevel(
Level).Directive;
667 unsigned OpenMPCaptureLevel)
const {
668 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
670 return CaptureRegions[OpenMPCaptureLevel];
674 const SharingMapTy *Parent = getSecondOnStackOrNull();
675 return Parent ? Parent->Directive : OMPD_unknown;
679 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
682 template <
typename ClauseType>
bool hasRequiresDeclWithClause()
const {
683 return llvm::any_of(RequiresDecls, [](
const OMPRequiresDecl *D) {
684 return llvm::any_of(D->
clauselists(), [](
const OMPClause *
C) {
685 return isa<ClauseType>(C);
692 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList)
const {
693 bool IsDuplicate =
false;
694 for (OMPClause *CNew : ClauseList) {
695 for (
const OMPRequiresDecl *D : RequiresDecls) {
696 for (
const OMPClause *CPrev : D->clauselists()) {
697 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
698 SemaRef.Diag(CNew->getBeginLoc(),
699 diag::err_omp_requires_clause_redeclaration)
701 SemaRef.Diag(CPrev->getBeginLoc(),
702 diag::note_omp_requires_previous_clause)
713 void addTargetDirLocation(SourceLocation LocStart) {
714 TargetLocations.push_back(LocStart);
718 void addAtomicDirectiveLoc(SourceLocation Loc) {
719 if (AtomicLocation.isInvalid())
720 AtomicLocation = Loc;
725 SourceLocation getAtomicDirectiveLoc()
const {
return AtomicLocation; }
728 ArrayRef<SourceLocation> getEncounteredTargetLocs()
const {
729 return TargetLocations;
733 void setDefaultDSANone(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_none;
735 getTopOfStack().DefaultAttrLoc = Loc;
738 void setDefaultDSAShared(SourceLocation Loc) {
739 getTopOfStack().DefaultAttr = DSA_shared;
740 getTopOfStack().DefaultAttrLoc = Loc;
743 void setDefaultDSAPrivate(SourceLocation Loc) {
744 getTopOfStack().DefaultAttr = DSA_private;
745 getTopOfStack().DefaultAttrLoc = Loc;
748 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
749 getTopOfStack().DefaultAttr = DSA_firstprivate;
750 getTopOfStack().DefaultAttrLoc = Loc;
753 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
754 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
755 getTopOfStack().DefaultAttrVCLoc = VCLoc;
758 void setDefaultDSAVCAll(SourceLocation VCLoc) {
759 getTopOfStack().DefaultVCAttr = DSA_VC_all;
760 getTopOfStack().DefaultAttrVCLoc = VCLoc;
763 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
764 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
765 getTopOfStack().DefaultAttrVCLoc = VCLoc;
768 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
769 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
770 getTopOfStack().DefaultAttrVCLoc = VCLoc;
775 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[
Kind];
776 DMI.ImplicitBehavior = M;
782 return getTopOfStack()
783 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
786 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
789 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
791 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
795 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
796 return ConstructTraits;
798 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
801 ConstructTraits.append(Traits.begin(), Traits.end());
803 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
804 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
805 assert(Top == Trait &&
"Something left a trait on the stack!");
811 DefaultDataSharingAttributes getDefaultDSA(
unsigned Level)
const {
812 return getStackSize() <=
Level ? DSA_unspecified
813 : getStackElemAtLevel(
Level).DefaultAttr;
815 DefaultDataSharingAttributes getDefaultDSA()
const {
816 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
818 SourceLocation getDefaultDSALocation()
const {
819 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
823 return isStackEmpty()
825 : getTopOfStack().DefaultmapMap[
Kind].ImplicitBehavior;
828 getDefaultmapModifierAtLevel(
unsigned Level,
830 return getStackElemAtLevel(
Level).DefaultmapMap[
Kind].ImplicitBehavior;
832 bool isDefaultmapCapturedByRef(
unsigned Level,
835 getDefaultmapModifierAtLevel(
Level, Kind);
836 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
837 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
838 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
839 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
840 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
841 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
842 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
849 case OMPC_DEFAULTMAP_scalar:
850 case OMPC_DEFAULTMAP_pointer:
852 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_default);
854 case OMPC_DEFAULTMAP_aggregate:
855 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
859 llvm_unreachable(
"Unexpected OpenMPDefaultmapClauseKind enum");
861 bool mustBeFirstprivateAtLevel(
unsigned Level,
864 getDefaultmapModifierAtLevel(
Level, Kind);
865 return mustBeFirstprivateBase(M, Kind);
869 return mustBeFirstprivateBase(M, Kind);
873 bool isThreadPrivate(VarDecl *D) {
874 const DSAVarData DVar = getTopDSA(D,
false);
879 void setOrderedRegion(
bool IsOrdered,
const Expr *Param,
880 OMPOrderedClause *Clause) {
882 getTopOfStack().OrderedRegion.emplace(Param, Clause);
884 getTopOfStack().OrderedRegion.reset();
888 bool isOrderedRegion()
const {
889 if (
const SharingMapTy *Top = getTopOfStackOrNull())
890 return Top->OrderedRegion.has_value();
894 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam()
const {
895 if (
const SharingMapTy *Top = getTopOfStackOrNull())
896 if (Top->OrderedRegion)
897 return *Top->OrderedRegion;
898 return std::make_pair(
nullptr,
nullptr);
902 bool isParentOrderedRegion()
const {
903 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
904 return Parent->OrderedRegion.has_value();
908 std::pair<const Expr *, OMPOrderedClause *>
909 getParentOrderedRegionParam()
const {
910 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
911 if (Parent->OrderedRegion)
912 return *Parent->OrderedRegion;
913 return std::make_pair(
nullptr,
nullptr);
916 void setRegionHasOrderConcurrent(
bool HasOrderConcurrent) {
917 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
921 bool isParentOrderConcurrent()
const {
922 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
923 return Parent->RegionHasOrderConcurrent;
927 void setNowaitRegion(
bool IsNowait =
true) {
928 getTopOfStack().NowaitRegion = IsNowait;
932 bool isParentNowaitRegion()
const {
933 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
934 return Parent->NowaitRegion;
938 void setUntiedRegion(
bool IsUntied =
true) {
939 getTopOfStack().UntiedRegion = IsUntied;
942 bool isUntiedRegion()
const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->UntiedRegion :
false;
947 void setParentCancelRegion(
bool Cancel =
true) {
948 if (SharingMapTy *Parent = getSecondOnStackOrNull())
949 Parent->CancelRegion |= Cancel;
952 bool isCancelRegion()
const {
953 const SharingMapTy *Top = getTopOfStackOrNull();
954 return Top ? Top->CancelRegion :
false;
958 void setParentHasScanDirective(SourceLocation Loc) {
959 if (SharingMapTy *Parent = getSecondOnStackOrNull())
960 Parent->PrevScanLocation = Loc;
963 bool doesParentHasScanDirective()
const {
964 const SharingMapTy *Top = getSecondOnStackOrNull();
965 return Top ? Top->PrevScanLocation.isValid() :
false;
968 SourceLocation getParentScanDirectiveLoc()
const {
969 const SharingMapTy *Top = getSecondOnStackOrNull();
970 return Top ? Top->PrevScanLocation : SourceLocation();
973 void setParentHasOrderedDirective(SourceLocation Loc) {
974 if (SharingMapTy *Parent = getSecondOnStackOrNull())
975 Parent->PrevOrderedLocation = Loc;
978 bool doesParentHasOrderedDirective()
const {
979 const SharingMapTy *Top = getSecondOnStackOrNull();
980 return Top ? Top->PrevOrderedLocation.isValid() :
false;
983 SourceLocation getParentOrderedDirectiveLoc()
const {
984 const SharingMapTy *Top = getSecondOnStackOrNull();
985 return Top ? Top->PrevOrderedLocation : SourceLocation();
989 void setAssociatedLoops(
unsigned Val) {
990 getTopOfStack().AssociatedLoops = Val;
992 getTopOfStack().HasMutipleLoops =
true;
995 unsigned getAssociatedLoops()
const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->AssociatedLoops : 0;
1000 bool hasMutipleLoops()
const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->HasMutipleLoops :
false;
1007 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1008 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1009 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1012 bool hasInnerTeamsRegion()
const {
1013 return getInnerTeamsRegionLoc().
isValid();
1016 SourceLocation getInnerTeamsRegionLoc()
const {
1017 const SharingMapTy *Top = getTopOfStackOrNull();
1018 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1021 Scope *getCurScope()
const {
1022 const SharingMapTy *Top = getTopOfStackOrNull();
1023 return Top ? Top->CurScope :
nullptr;
1025 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1026 SourceLocation getConstructLoc()
const {
1027 const SharingMapTy *Top = getTopOfStackOrNull();
1028 return Top ? Top->ConstructLoc : SourceLocation();
1033 bool checkMappableExprComponentListsForDecl(
1034 const ValueDecl *VD,
bool CurrentRegionOnly,
1035 const llvm::function_ref<
1047 if (CurrentRegionOnly)
1050 std::advance(SI, 1);
1052 for (; SI != SE; ++SI) {
1053 auto MI = SI->MappedExprComponents.find(VD);
1054 if (MI != SI->MappedExprComponents.end())
1056 MI->second.Components)
1057 if (Check(L, MI->second.Kind))
1065 bool checkMappableExprComponentListsForDeclAtLevel(
1066 const ValueDecl *VD,
unsigned Level,
1067 const llvm::function_ref<
1071 if (getStackSize() <=
Level)
1074 const SharingMapTy &StackElem = getStackElemAtLevel(
Level);
1075 auto MI = StackElem.MappedExprComponents.find(VD);
1076 if (MI != StackElem.MappedExprComponents.end())
1078 MI->second.Components)
1079 if (Check(L, MI->second.Kind))
1086 void addMappableExpressionComponents(
1087 const ValueDecl *VD,
1090 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1092 MEC.Components.resize(MEC.Components.size() + 1);
1093 MEC.Components.back().append(Components.begin(), Components.end());
1094 MEC.Kind = WhereFoundClauseKind;
1097 unsigned getNestingLevel()
const {
1098 assert(!isStackEmpty());
1099 return getStackSize() - 1;
1101 void addDoacrossDependClause(OMPClause *
C,
const OperatorOffsetTy &OpsOffs) {
1102 SharingMapTy *Parent = getSecondOnStackOrNull();
1104 Parent->DoacrossDepends.try_emplace(
C, OpsOffs);
1106 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1107 getDoacrossDependClauses()
const {
1108 const SharingMapTy &StackElem = getTopOfStack();
1110 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1111 return llvm::make_range(Ref.begin(), Ref.end());
1113 return llvm::make_range(StackElem.DoacrossDepends.end(),
1114 StackElem.DoacrossDepends.end());
1118 void addMappedClassesQualTypes(QualType QT) {
1119 SharingMapTy &StackElem = getTopOfStack();
1120 StackElem.MappedClassesQualTypes.insert(QT);
1124 bool isClassPreviouslyMapped(QualType QT)
const {
1125 const SharingMapTy &StackElem = getTopOfStack();
1126 return StackElem.MappedClassesQualTypes.contains(QT);
1130 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1131 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1132 E->
getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1133 "Expected declare target link global.");
1134 for (
auto &Elem : *
this) {
1136 Elem.DeclareTargetLinkVarDecls.push_back(E);
1144 ArrayRef<DeclRefExpr *> getLinkGlobals()
const {
1146 "Expected target executable directive.");
1147 return getTopOfStack().DeclareTargetLinkVarDecls;
1151 void addInnerAllocatorExpr(Expr *E) {
1152 getTopOfStack().InnerUsedAllocators.push_back(E);
1155 ArrayRef<Expr *> getInnerAllocators()
const {
1156 return getTopOfStack().InnerUsedAllocators;
1160 void addImplicitTaskFirstprivate(
unsigned Level, Decl *D) {
1161 getStackElemAtLevel(
Level).ImplicitTaskFirstprivates.insert(D);
1164 bool isImplicitTaskFirstprivate(Decl *D)
const {
1165 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1169 void addUsesAllocatorsDecl(
const Decl *D, UsesAllocatorsDeclKind Kind) {
1170 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1174 std::optional<UsesAllocatorsDeclKind>
1175 isUsesAllocatorsDecl(
unsigned Level,
const Decl *D)
const {
1176 const SharingMapTy &StackElem = getTopOfStack();
1177 auto I = StackElem.UsesAllocatorsDecls.find(D);
1178 if (I == StackElem.UsesAllocatorsDecls.end())
1179 return std::nullopt;
1180 return I->getSecond();
1182 std::optional<UsesAllocatorsDeclKind>
1183 isUsesAllocatorsDecl(
const Decl *D)
const {
1184 const SharingMapTy &StackElem = getTopOfStack();
1185 auto I = StackElem.UsesAllocatorsDecls.find(D);
1186 if (I == StackElem.UsesAllocatorsDecls.end())
1187 return std::nullopt;
1188 return I->getSecond();
1191 void addDeclareMapperVarRef(Expr *Ref) {
1192 SharingMapTy &StackElem = getTopOfStack();
1193 StackElem.DeclareMapperVar = Ref;
1195 const Expr *getDeclareMapperVarRef()
const {
1196 const SharingMapTy *Top = getTopOfStackOrNull();
1197 return Top ? Top->DeclareMapperVar :
nullptr;
1201 void addIteratorVarDecl(VarDecl *VD) {
1202 SharingMapTy &StackElem = getTopOfStack();
1206 bool isIteratorVarDecl(
const VarDecl *VD)
const {
1207 const SharingMapTy *Top = getTopOfStackOrNull();
1214 VarDecl *getImplicitFDCapExprDecl(
const FieldDecl *FD)
const {
1215 const_iterator I = begin();
1216 const_iterator EndI = end();
1217 size_t StackLevel = getStackSize();
1218 for (; I != EndI; ++I) {
1219 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1223 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1226 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1227 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1232 bool isImplicitDefaultFirstprivateFD(VarDecl *VD)
const {
1233 const_iterator I = begin();
1234 const_iterator EndI = end();
1235 for (; I != EndI; ++I)
1236 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1240 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1246 void addImplicitDefaultFirstprivateFD(
const FieldDecl *FD, VarDecl *VD) {
1247 iterator I = begin();
1248 const_iterator EndI = end();
1249 size_t StackLevel = getStackSize();
1250 for (; I != EndI; ++I) {
1251 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1252 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1257 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1267 DKind == OMPD_unknown;
1273 if (
const auto *FE = dyn_cast<FullExpr>(E))
1274 E = FE->getSubExpr();
1276 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1277 E = MTE->getSubExpr();
1279 while (
const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1280 E = Binder->getSubExpr();
1282 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1283 E = ICE->getSubExprAsWritten();
1292 if (
const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1293 if (
const auto *ME = dyn_cast<MemberExpr>(
getExprAsWritten(CED->getInit())))
1294 D = ME->getMemberDecl();
1306 if (
C == OMPC_threadprivate)
1307 return getOpenMPClauseName(
C).str() +
" or thread local";
1308 return getOpenMPClauseName(
C).str();
1314 auto *VD = dyn_cast<VarDecl>(D);
1315 const auto *FD = dyn_cast<FieldDecl>(D);
1317 if (Iter == end()) {
1324 DVar.CKind = OMPC_shared;
1331 DVar.CKind = OMPC_shared;
1335 DVar.CKind = OMPC_shared;
1346 DVar.CKind = OMPC_private;
1350 DVar.DKind = Iter->Directive;
1353 if (Iter->SharingMap.count(D)) {
1354 const DSAInfo &
Data = Iter->SharingMap.lookup(D);
1355 DVar.RefExpr =
Data.RefExpr.getPointer();
1356 DVar.PrivateCopy =
Data.PrivateCopy;
1357 DVar.CKind =
Data.Attributes;
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 DVar.Modifier =
Data.Modifier;
1360 DVar.AppliedToPointee =
Data.AppliedToPointee;
1364 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1365 switch (Iter->DefaultVCAttr) {
1366 case DSA_VC_aggregate:
1370 case DSA_VC_pointer:
1388 DVar.CKind = OMPC_shared;
1389 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1393 case DSA_firstprivate:
1396 DVar.CKind = OMPC_unknown;
1398 DVar.CKind = OMPC_firstprivate;
1400 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1408 DVar.CKind = OMPC_unknown;
1410 DVar.CKind = OMPC_private;
1412 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1414 case DSA_unspecified:
1419 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1423 DVar.CKind = OMPC_shared;
1433 DSAVarData DVarTemp;
1434 const_iterator I = Iter, E = end();
1442 DVarTemp = getDSA(I, D);
1443 if (DVarTemp.CKind != OMPC_shared) {
1444 DVar.RefExpr =
nullptr;
1445 DVar.CKind = OMPC_firstprivate;
1448 }
while (I != E && !isImplicitTaskingRegion(I->Directive));
1450 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1459 return getDSA(++Iter, D);
1462const Expr *DSAStackTy::addUniqueAligned(
const ValueDecl *D,
1463 const Expr *NewDE) {
1464 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1466 SharingMapTy &StackElem = getTopOfStack();
1467 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1469 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1472 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1476const Expr *DSAStackTy::addUniqueNontemporal(
const ValueDecl *D,
1477 const Expr *NewDE) {
1478 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1480 SharingMapTy &StackElem = getTopOfStack();
1481 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1483 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1486 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1490void DSAStackTy::addLoopControlVariable(
const ValueDecl *D, VarDecl *
Capture) {
1491 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1493 SharingMapTy &StackElem = getTopOfStack();
1494 StackElem.LCVMap.try_emplace(
1495 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1498const DSAStackTy::LCDeclInfo
1499DSAStackTy::isLoopControlVariable(
const ValueDecl *D)
const {
1500 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1502 const SharingMapTy &StackElem = getTopOfStack();
1503 auto It = StackElem.LCVMap.find(D);
1504 if (It != StackElem.LCVMap.end())
1506 return {0,
nullptr};
1509const DSAStackTy::LCDeclInfo
1510DSAStackTy::isLoopControlVariable(
const ValueDecl *D,
unsigned Level)
const {
1511 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1513 for (
unsigned I =
Level + 1; I > 0; --I) {
1514 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1515 auto It = StackElem.LCVMap.find(D);
1516 if (It != StackElem.LCVMap.end())
1519 return {0,
nullptr};
1522const DSAStackTy::LCDeclInfo
1523DSAStackTy::isParentLoopControlVariable(
const ValueDecl *D)
const {
1524 const SharingMapTy *Parent = getSecondOnStackOrNull();
1525 assert(Parent &&
"Data-sharing attributes stack is empty");
1527 auto It = Parent->LCVMap.find(D);
1528 if (It != Parent->LCVMap.end())
1530 return {0,
nullptr};
1533const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1534 const SharingMapTy *Parent = getSecondOnStackOrNull();
1535 assert(Parent &&
"Data-sharing attributes stack is empty");
1536 if (Parent->LCVMap.size() < I)
1538 for (
const auto &Pair : Parent->LCVMap)
1539 if (Pair.second.first == I)
1544void DSAStackTy::addDSA(
const ValueDecl *D,
const Expr *E,
OpenMPClauseKind A,
1545 DeclRefExpr *PrivateCopy,
unsigned Modifier,
1546 bool AppliedToPointee) {
1548 if (A == OMPC_threadprivate) {
1549 DSAInfo &
Data = Threadprivates[D];
1550 Data.Attributes = A;
1551 Data.RefExpr.setPointer(E);
1552 Data.PrivateCopy =
nullptr;
1553 Data.Modifier = Modifier;
1554 }
else if (A == OMPC_groupprivate) {
1555 DSAInfo &
Data = Groupprivates[D];
1556 Data.Attributes = A;
1557 Data.RefExpr.setPointer(E);
1558 Data.PrivateCopy =
nullptr;
1559 Data.Modifier = Modifier;
1561 DSAInfo &
Data = getTopOfStack().SharingMap[D];
1562 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1563 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1564 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1565 (isLoopControlVariable(D).first && A == OMPC_private));
1566 Data.Modifier = Modifier;
1567 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1568 Data.RefExpr.setInt(
true);
1571 const bool IsLastprivate =
1572 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1573 Data.Attributes = A;
1574 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1575 Data.PrivateCopy = PrivateCopy;
1576 Data.AppliedToPointee = AppliedToPointee;
1578 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1579 Data.Modifier = Modifier;
1580 Data.Attributes = A;
1581 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1582 Data.PrivateCopy =
nullptr;
1583 Data.AppliedToPointee = AppliedToPointee;
1590 StringRef Name,
const AttrVec *Attrs =
nullptr,
1605 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1612 bool RefersToCapture =
false) {
1620void DSAStackTy::addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
1623 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1625 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1626 "Additional reduction info may be specified only for reduction items.");
1627 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1628 assert(ReductionData.ReductionRange.isInvalid() &&
1629 (getTopOfStack().
Directive == OMPD_taskgroup ||
1633 "Additional reduction info may be specified only once for reduction "
1635 ReductionData.set(BOK, SR);
1636 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1637 if (!TaskgroupReductionRef) {
1640 TaskgroupReductionRef =
1645void DSAStackTy::addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
1646 const Expr *ReductionRef) {
1648 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1650 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1651 "Additional reduction info may be specified only for reduction items.");
1652 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1653 assert(ReductionData.ReductionRange.isInvalid() &&
1654 (getTopOfStack().
Directive == OMPD_taskgroup ||
1658 "Additional reduction info may be specified only once for reduction "
1660 ReductionData.set(ReductionRef, SR);
1661 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1662 if (!TaskgroupReductionRef) {
1665 TaskgroupReductionRef =
1670const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1672 Expr *&TaskgroupDescriptor)
const {
1674 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1675 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1676 const DSAInfo &
Data = I->SharingMap.lookup(D);
1677 if (
Data.Attributes != OMPC_reduction ||
1678 Data.Modifier != OMPC_REDUCTION_task)
1680 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1681 if (!ReductionData.ReductionOp ||
1683 return DSAVarData();
1684 SR = ReductionData.ReductionRange;
1686 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1687 "expression for the descriptor is not "
1689 TaskgroupDescriptor = I->TaskgroupReductionRef;
1690 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1691 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1694 return DSAVarData();
1697const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1698 const ValueDecl *D, SourceRange &SR,
const Expr *&ReductionRef,
1699 Expr *&TaskgroupDescriptor)
const {
1701 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1702 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1703 const DSAInfo &
Data = I->SharingMap.lookup(D);
1704 if (
Data.Attributes != OMPC_reduction ||
1705 Data.Modifier != OMPC_REDUCTION_task)
1707 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1708 if (!ReductionData.ReductionOp ||
1710 return DSAVarData();
1711 SR = ReductionData.ReductionRange;
1713 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1714 "expression for the descriptor is not "
1716 TaskgroupDescriptor = I->TaskgroupReductionRef;
1717 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1718 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1721 return DSAVarData();
1724bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I)
const {
1726 for (const_iterator E = end(); I != E; ++I) {
1727 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1730 Scope *TopScope = I->CurScope->getParent();
1731 Scope *CurScope = getCurScope();
1732 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(D))
1734 return CurScope != TopScope;
1737 if (I->Context == DC)
1746 bool AcceptIfMutable =
true,
1747 bool *IsClassType =
nullptr) {
1749 Type =
Type.getNonReferenceType().getCanonicalType();
1750 bool IsConstant =
Type.isConstant(Context);
1751 Type = Context.getBaseElementType(
Type);
1755 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1757 RD = CTD->getTemplatedDecl();
1767 bool AcceptIfMutable =
true,
1768 bool ListItemNotVar =
false) {
1772 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1773 : IsClassType ? diag::err_omp_const_not_mutable_variable
1774 : diag::err_omp_const_variable;
1776 if (!ListItemNotVar && D) {
1777 const VarDecl *VD = dyn_cast<VarDecl>(D);
1781 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1789const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1794 auto *VD = dyn_cast<VarDecl>(D);
1795 auto TI = Threadprivates.find(D);
1796 if (TI != Threadprivates.end()) {
1797 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1798 DVar.CKind = OMPC_threadprivate;
1799 DVar.Modifier = TI->getSecond().Modifier;
1802 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1805 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1806 DVar.CKind = OMPC_threadprivate;
1807 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1814 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1821 DVar.CKind = OMPC_threadprivate;
1822 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1827 !isLoopControlVariable(D).first) {
1828 const_iterator IterTarget =
1829 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1832 if (IterTarget != end()) {
1833 const_iterator ParentIterTarget = IterTarget + 1;
1834 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1835 if (isOpenMPLocal(VD, Iter)) {
1839 DVar.CKind = OMPC_threadprivate;
1843 if (!isClauseParsingMode() || IterTarget != begin()) {
1844 auto DSAIter = IterTarget->SharingMap.find(D);
1845 if (DSAIter != IterTarget->SharingMap.end() &&
1847 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1848 DVar.CKind = OMPC_threadprivate;
1851 const_iterator End = end();
1853 D, std::distance(ParentIterTarget, End),
1857 IterTarget->ConstructLoc);
1858 DVar.CKind = OMPC_threadprivate;
1878 const_iterator I = begin();
1879 const_iterator EndI = end();
1880 if (FromParent && I != EndI)
1883 auto It = I->SharingMap.find(D);
1884 if (It != I->SharingMap.end()) {
1885 const DSAInfo &
Data = It->getSecond();
1886 DVar.RefExpr =
Data.RefExpr.getPointer();
1887 DVar.PrivateCopy =
Data.PrivateCopy;
1888 DVar.CKind =
Data.Attributes;
1889 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1890 DVar.DKind = I->Directive;
1891 DVar.Modifier =
Data.Modifier;
1892 DVar.AppliedToPointee =
Data.AppliedToPointee;
1897 DVar.CKind = OMPC_shared;
1904 if (SemaRef.
LangOpts.OpenMP <= 31) {
1912 DSAVarData DVarTemp = hasInnermostDSA(
1915 return C == OMPC_firstprivate ||
C == OMPC_shared;
1917 MatchesAlways, FromParent);
1918 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1921 DVar.CKind = OMPC_shared;
1928 const_iterator I = begin();
1929 const_iterator EndI = end();
1930 if (FromParent && I != EndI)
1934 auto It = I->SharingMap.find(D);
1935 if (It != I->SharingMap.end()) {
1936 const DSAInfo &
Data = It->getSecond();
1937 DVar.RefExpr =
Data.RefExpr.getPointer();
1938 DVar.PrivateCopy =
Data.PrivateCopy;
1939 DVar.CKind =
Data.Attributes;
1940 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1941 DVar.DKind = I->Directive;
1942 DVar.Modifier =
Data.Modifier;
1943 DVar.AppliedToPointee =
Data.AppliedToPointee;
1949const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1950 bool FromParent)
const {
1951 if (isStackEmpty()) {
1953 return getDSA(I, D);
1956 const_iterator StartI = begin();
1957 const_iterator EndI = end();
1958 if (FromParent && StartI != EndI)
1960 return getDSA(StartI, D);
1963const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1964 unsigned Level)
const {
1965 if (getStackSize() <=
Level)
1966 return DSAVarData();
1968 const_iterator StartI = std::next(begin(), getStackSize() - 1 -
Level);
1969 return getDSA(StartI, D);
1972const DSAStackTy::DSAVarData
1973DSAStackTy::hasDSA(ValueDecl *D,
1975 DefaultDataSharingAttributes)>
1978 bool FromParent)
const {
1982 const_iterator I = begin();
1983 const_iterator EndI = end();
1984 if (FromParent && I != EndI)
1986 for (; I != EndI; ++I) {
1987 if (!DPred(I->Directive) &&
1988 !isImplicitOrExplicitTaskingRegion(I->Directive))
1990 const_iterator NewI = I;
1991 DSAVarData DVar = getDSA(NewI, D);
1992 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1998const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1999 ValueDecl *D,
const llvm::function_ref<
bool(
OpenMPClauseKind,
bool)> CPred,
2001 bool FromParent)
const {
2005 const_iterator StartI = begin();
2006 const_iterator EndI = end();
2007 if (FromParent && StartI != EndI)
2009 if (StartI == EndI || !DPred(StartI->Directive))
2011 const_iterator NewI = StartI;
2012 DSAVarData DVar = getDSA(NewI, D);
2013 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2018bool DSAStackTy::hasExplicitDSA(
2021 unsigned Level,
bool NotLastprivate)
const {
2022 if (getStackSize() <=
Level)
2025 const SharingMapTy &StackElem = getStackElemAtLevel(
Level);
2026 auto I = StackElem.SharingMap.find(D);
2027 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2028 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2029 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2032 auto LI = StackElem.LCVMap.find(D);
2033 if (LI != StackElem.LCVMap.end())
2034 return CPred(OMPC_private,
false);
2038bool DSAStackTy::hasExplicitDirective(
2040 unsigned Level)
const {
2041 if (getStackSize() <=
Level)
2043 const SharingMapTy &StackElem = getStackElemAtLevel(
Level);
2044 return DPred(StackElem.Directive);
2047bool DSAStackTy::hasDirective(
2049 const DeclarationNameInfo &, SourceLocation)>
2051 bool FromParent)
const {
2053 size_t Skip = FromParent ? 2 : 1;
2054 for (const_iterator I = begin() + std::min(
Skip, getStackSize()), E = end();
2056 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2062void SemaOpenMP::InitDataSharingAttributesStack() {
2063 VarDataSharingAttributesStack =
new DSAStackTy(SemaRef);
2066#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2068void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2070void SemaOpenMP::popOpenMPFunctionRegion(
const FunctionScopeInfo *OldFSI) {
2076 "Expected OpenMP device compilation.");
2082enum class FunctionEmissionStatus {
2089SemaBase::SemaDiagnosticBuilder
2093 "Expected OpenMP device compilation.");
2095 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2100 Kind = SemaDiagnosticBuilder::K_Immediate;
2111 ? SemaDiagnosticBuilder::K_Deferred
2112 : SemaDiagnosticBuilder::K_Immediate;
2116 Kind = SemaDiagnosticBuilder::K_Nop;
2119 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2131 "Expected OpenMP host compilation.");
2133 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2138 Kind = SemaDiagnosticBuilder::K_Immediate;
2141 Kind = SemaDiagnosticBuilder::K_Deferred;
2146 Kind = SemaDiagnosticBuilder::K_Nop;
2156 if (LO.OpenMP <= 45) {
2158 return OMPC_DEFAULTMAP_scalar;
2159 return OMPC_DEFAULTMAP_aggregate;
2162 return OMPC_DEFAULTMAP_pointer;
2164 return OMPC_DEFAULTMAP_scalar;
2165 return OMPC_DEFAULTMAP_aggregate;
2169 unsigned OpenMPCaptureLevel)
const {
2170 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2173 bool IsByRef =
true;
2179 bool IsVariableUsedInMapClause =
false;
2244 bool IsVariableAssociatedWithSection =
false;
2245 bool IsVariableItselfMapped =
false;
2247 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2249 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2250 &IsVariableItselfMapped,
2257 if (WhereFoundClauseKind != OMPC_map &&
2258 WhereFoundClauseKind != OMPC_has_device_addr)
2261 auto EI = MapExprComponents.rbegin();
2262 auto EE = MapExprComponents.rend();
2264 assert(EI != EE &&
"Invalid map expression!");
2267 EI->getAssociatedDeclaration() == D) {
2268 IsVariableUsedInMapClause =
true;
2274 if (MapExprComponents.size() == 1) {
2275 IsVariableItselfMapped =
true;
2283 auto Last = std::prev(EE);
2285 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2286 if ((UO && UO->getOpcode() == UO_Deref) ||
2291 IsVariableAssociatedWithSection =
true;
2302 if (IsVariableUsedInMapClause) {
2319 IsByRef = IsVariableItselfMapped ||
2325 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2328 DSAStack->isDefaultmapCapturedByRef(
2333 return K == OMPC_reduction && !AppliedToPointee;
2341 ((IsVariableUsedInMapClause &&
2342 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2347 return K == OMPC_firstprivate ||
2348 (K == OMPC_reduction && AppliedToPointee);
2351 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2358 !((
DSAStack->getDefaultDSA() == DSA_firstprivate ||
2359 DSAStack->getDefaultDSA() == DSA_private) &&
2363 !
DSAStack->isLoopControlVariable(D, Level).first);
2380unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2381 assert(getLangOpts().OpenMP);
2382 return DSAStack->getNestingLevel();
2392 !
DSAStack->isClauseParsingMode()) ||
2405 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2408 DefaultDataSharingAttributes DefaultAttr) {
2410 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2414 if (DVarPrivate.CKind != OMPC_unknown)
2420 Expr *CaptureExpr,
bool WithInit,
2426 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2429 auto *VD = dyn_cast<VarDecl>(D);
2438 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2448 DSAStackTy::DSAVarData DVarTop =
2450 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2455 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2459 llvm::reverse(
SemaRef.FunctionScopes),
2460 CheckScopeInfo ? (
SemaRef.FunctionScopes.size() - (StopAt + 1))
2464 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2470 assert(CSI &&
"Failed to find CapturedRegionScopeInfo");
2481 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2487 if (CheckScopeInfo) {
2488 bool OpenMPFound =
false;
2489 for (
unsigned I = StopAt + 1; I > 0; --I) {
2493 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2503 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2504 (!
DSAStack->isClauseParsingMode() ||
2505 DSAStack->getParentDirective() != OMPD_unknown)) {
2506 auto &&Info =
DSAStack->isLoopControlVariable(D);
2509 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2510 (VD &&
DSAStack->isForceVarCapturing()))
2511 return VD ? VD : Info.second;
2512 DSAStackTy::DSAVarData DVarTop =
2514 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2516 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2523 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2531 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2532 ((
DSAStack->getDefaultDSA() != DSA_none &&
2533 DSAStack->getDefaultDSA() != DSA_private &&
2534 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2535 DVarTop.CKind == OMPC_shared))
2537 auto *FD = dyn_cast<FieldDecl>(D);
2538 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2539 !DVarPrivate.PrivateCopy) {
2540 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2543 DefaultDataSharingAttributes DefaultAttr) {
2545 (DefaultAttr == DSA_firstprivate ||
2546 DefaultAttr == DSA_private);
2550 if (DVarPrivate.CKind == OMPC_unknown)
2556 if (
SemaRef.getCurrentThisType().isNull())
2570 SemaRef.CurContext->getParent(),
false);
2574 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2577 if (DVarPrivate.CKind != OMPC_unknown ||
2578 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2579 DSAStack->getDefaultDSA() == DSA_private ||
2580 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2586void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2587 unsigned Level)
const {
2588 FunctionScopesIndex -= getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
2592 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2598 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2600 DSAStack->resetPossibleLoopCounter();
2606 unsigned CapLevel)
const {
2607 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2608 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2609 (!
DSAStack->isClauseParsingMode() ||
2610 DSAStack->getParentDirective() != OMPD_unknown)) {
2611 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2614 DefaultDataSharingAttributes DefaultAttr) {
2616 DefaultAttr == DSA_private;
2622 !
DSAStack->isLoopControlVariable(D).first)
2623 return OMPC_private;
2626 bool IsTriviallyCopyable =
2637 (IsTriviallyCopyable ||
2643 return OMPC_firstprivate;
2644 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2645 if (DVar.CKind != OMPC_shared &&
2646 !
DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2647 DSAStack->addImplicitTaskFirstprivate(Level, D);
2648 return OMPC_firstprivate;
2655 DSAStack->resetPossibleLoopCounter(D);
2657 return OMPC_private;
2660 DSAStack->isLoopControlVariable(D).first) &&
2665 return OMPC_private;
2667 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2673 return OMPC_private;
2678 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2679 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2680 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2681 return OMPC_private;
2685 (
DSAStack->isClauseParsingMode() &&
2686 DSAStack->getClauseParsingMode() == OMPC_private) ||
2691 return K == OMPD_taskgroup ||
2692 ((isOpenMPParallelDirective(K) ||
2693 isOpenMPWorksharingDirective(K)) &&
2694 !isOpenMPSimdDirective(K));
2697 DSAStack->isTaskgroupReductionRef(D, Level)))
2704 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2707 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2708 const unsigned NewLevel = I - 1;
2712 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2720 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2730 if (
DSAStack->mustBeFirstprivateAtLevel(
2732 OMPC = OMPC_firstprivate;
2736 if (OMPC != OMPC_unknown)
2738 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2742 unsigned CaptureLevel)
const {
2743 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2748 const auto *VD = dyn_cast<VarDecl>(D);
2752 Regions[CaptureLevel] != OMPD_task;
2756 unsigned CaptureLevel)
const {
2757 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2760 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2764 DSAStackTy::DSAVarData TopDVar =
2766 unsigned NumLevels =
2771 return (NumLevels == CaptureLevel + 1 &&
2772 (TopDVar.CKind != OMPC_shared ||
2773 DSAStack->getDefaultDSA() == DSA_firstprivate));
2776 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2777 if (DVar.CKind != OMPC_shared)
2779 }
while (Level > 0);
2785void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2789 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2794 "Not in OpenMP declare variant scope!");
2796 OMPDeclareVariantScopes.pop_back();
2802 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2803 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2807 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2810 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2811 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2814 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2815 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2816 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2818 StringRef HostDevTy =
2820 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2821 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2822 diag::note_omp_marked_device_type_here)
2828 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2832 for (OMPDeclareVariantAttr *A :
2833 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2836 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2837 OMPDeclareTargetDeclAttr::getDeviceType(
2838 VariantFD->getMostRecentDecl());
2839 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2845 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2849 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2850 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2851 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2852 diag::note_omp_marked_device_type_here)
2860 DSAStack->push(DKind, DirName, CurScope, Loc);
2861 SemaRef.PushExpressionEvaluationContext(
2870 DSAStack->setClauseParsingMode(OMPC_unknown);
2871 SemaRef.CleanupVarDeclMarking();
2874static std::pair<ValueDecl *, bool>
2876 SourceRange &ERange,
bool AllowArraySection =
false,
2877 bool AllowAssumedSizeArray =
false, StringRef DiagType =
"");
2882 bool InscanFound =
false;
2889 if (
C->getClauseKind() != OMPC_reduction)
2892 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2894 InscanLoc = RC->getModifierLoc();
2897 if (RC->getModifier() == OMPC_REDUCTION_task) {
2907 S.
Diag(RC->getModifierLoc(),
2908 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2914 if (
C->getClauseKind() != OMPC_reduction)
2917 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2920 : RC->getModifierLoc(),
2921 diag::err_omp_inscan_reduction_expected);
2922 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2925 for (
Expr *Ref : RC->varlist()) {
2926 assert(Ref &&
"NULL expr in OpenMP reduction clause.");
2929 Expr *SimpleRefExpr = Ref;
2936 S.
Diag(Ref->getExprLoc(),
2937 diag::err_omp_reduction_not_inclusive_exclusive)
2938 << Ref->getSourceRange();
2946 ArrayRef<OMPClause *> Clauses);
2947static DeclRefExpr *
buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2952 const DSAStackTy::DSAVarData &DVar,
2953 bool IsLoopIterVar =
false);
2962 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2964 for (
Expr *DE : Clause->varlist()) {
2965 if (DE->isValueDependent() || DE->isTypeDependent()) {
2966 PrivateCopies.push_back(
nullptr);
2972 const DSAStackTy::DSAVarData DVar =
2974 if (DVar.CKind != OMPC_lastprivate) {
2977 PrivateCopies.push_back(
nullptr);
2988 SemaRef.ActOnUninitializedDecl(VDPrivate);
2990 PrivateCopies.push_back(
nullptr);
2996 Clause->setPrivateCopies(PrivateCopies);
3002 for (
Expr *RefExpr : Clause->varlist()) {
3003 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
3006 Expr *SimpleRefExpr = RefExpr;
3010 PrivateRefs.push_back(RefExpr);
3015 const DSAStackTy::DSAVarData DVar =
3017 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
3020 Clause->setPrivateRefs(PrivateRefs);
3024 for (
unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3032 DSAStackTy::DSAVarData DVar =
3038 Expr *MapExpr =
nullptr;
3040 DSAStack->checkMappableExprComponentListsForDecl(
3046 auto MI = MapExprComponents.rbegin();
3047 auto ME = MapExprComponents.rend();
3049 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3050 VD->getCanonicalDecl()) {
3051 MapExpr = MI->getAssociatedExpression();
3056 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3061 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3062 << MapExpr->getSourceRange();
3067 if (
const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3069 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
3070 FinalizeLastprivate(Clause);
3071 }
else if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
3072 FinalizeNontemporal(Clause);
3073 }
else if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
3074 FinalizeAllocators(Clause);
3089 Expr *NumIterations, Sema &SemaRef,
3090 Scope *S, DSAStackTy *Stack);
3093 OMPLoopBasedDirective::HelperExprs &B,
3094 DSAStackTy *Stack) {
3096 "loop exprs were not built");
3103 auto *LC = dyn_cast<OMPLinearClause>(
C);
3107 B.NumIterations, SemaRef,
3117class VarDeclFilterCCC final :
public CorrectionCandidateCallback {
3122 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3123 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3125 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3133 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3134 return std::make_unique<VarDeclFilterCCC>(*
this);
3138class VarOrFuncDeclFilterCCC final :
public CorrectionCandidateCallback {
3143 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3144 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3154 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3155 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3168 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3177 VarDeclFilterCCC CCC(
SemaRef);
3183 SemaRef.PDiag(Lookup.
empty() ? diag::err_undeclared_var_use_suggest
3184 : diag::err_omp_expected_var_arg_suggest)
3186 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3189 : diag::err_omp_expected_var_arg)
3202 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3204 Diag(Id.
getLoc(), diag::err_omp_global_var_arg)
3205 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->
isStaticLocal();
3209 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3220 !
SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3222 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3226 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3237 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3241 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3250 (!
SemaRef.getCurLexicalContext()->isFileContext() ||
3251 !
SemaRef.getCurLexicalContext()->Encloses(
3254 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3258 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3267 !
SemaRef.isDeclInScope(ND,
SemaRef.getCurLexicalContext(), CurScope)) {
3269 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3273 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3281 if ((Kind == OMPD_threadprivate && VD->
isUsed() &&
3283 (Kind == OMPD_groupprivate && VD->
isUsed())) {
3285 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3300 SemaRef.CurContext->addDecl(D);
3310 Diag(Loc, diag::err_omp_unexpected_directive)
3311 << getOpenMPDirectiveName(OMPD_groupprivate,
getLangOpts().OpenMP);
3315 SemaRef.CurContext->addDecl(D);
3322class LocalVarRefChecker final
3328 if (
const auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
3331 diag::err_omp_local_var_in_threadprivate_init)
3333 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3340 bool VisitStmt(
const Stmt *S) {
3341 for (
const Stmt *Child : S->
children()) {
3342 if (Child && Visit(Child))
3347 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3351OMPThreadPrivateDecl *
3356 for (
Expr *RefExpr : VarList) {
3374 if (
SemaRef.RequireCompleteType(
3375 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3383 Diag(ILoc, diag::err_omp_ref_type_arg)
3384 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3389 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3397 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3402 Diag(ILoc, diag::err_omp_var_thread_local)
3407 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3415 LocalVarRefChecker Checker(
SemaRef);
3416 if (Checker.Visit(
Init))
3420 Vars.push_back(RefExpr);
3421 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3422 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3425 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3428 if (!Vars.empty()) {
3441 for (
Expr *RefExpr : VarList) {
3459 if (
SemaRef.RequireCompleteType(
3460 ILoc, VD->
getType(), diag::err_omp_groupprivate_incomplete_type)) {
3466 Diag(ILoc, diag::err_omp_ref_type_arg)
3467 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->
getType();
3471 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3479 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3484 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3489 Vars.push_back(RefExpr);
3490 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3491 VD->
addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3494 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3497 if (!Vars.empty()) {
3505static OMPAllocateDeclAttr::AllocatorTypeTy
3508 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3512 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3513 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3514 llvm::FoldingSetNodeID AEId;
3517 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3518 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3519 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3520 llvm::FoldingSetNodeID DAEId;
3523 if (AEId == DAEId) {
3524 AllocatorKindRes = AllocatorKind;
3528 return AllocatorKindRes;
3533 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3534 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3536 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3537 Expr *PrevAllocator = A->getAllocator();
3538 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3540 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3541 if (AllocatorsMatch &&
3542 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3543 Allocator && PrevAllocator) {
3546 llvm::FoldingSetNodeID AEId, PAEId;
3549 AllocatorsMatch = AEId == PAEId;
3551 if (!AllocatorsMatch) {
3553 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3557 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3559 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3567 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3569 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3570 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3571 << (Allocator ? 1 : 0) << AllocatorStream.str()
3572 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3574 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3575 << PrevAllocatorRange;
3583 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3585 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3598 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3599 Allocator, Alignment, SR);
3602 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3608 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3609 Expr *Alignment =
nullptr;
3610 Expr *Allocator =
nullptr;
3611 if (Clauses.empty()) {
3617 !
DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3618 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3621 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3622 Allocator = AC->getAllocator();
3623 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3624 Alignment = AC->getAlignment();
3626 llvm_unreachable(
"Unexpected clause on allocate directive");
3628 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3631 for (
Expr *RefExpr : VarList) {
3637 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3645 AllocatorKind, Allocator))
3653 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3655 diag::err_omp_expected_predefined_allocator)
3660 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3666 Vars.push_back(RefExpr);
3673 Owner =
SemaRef.getCurLexicalContext();
3684 if (!
SemaRef.CurContext->isFileContext()) {
3685 Diag(Loc, diag::err_omp_invalid_scope) <<
"requires";
3689 SemaRef.CurContext->addDecl(D);
3699 bool SkippedClauses) {
3700 if (!SkippedClauses && Assumptions.empty()) {
3702 Diag(Loc, diag::err_omp_no_clause_for_directive)
3703 << llvm::omp::getAllAssumeClauseOptions()
3704 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3708 OMPAssumeAttr::Create(
getASTContext(), llvm::join(Assumptions,
","), Loc);
3709 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3710 OMPAssumeScoped.push_back(AA);
3715 if (Assumptions.empty())
3718 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3719 "Unexpected omp assumption directive!");
3720 OMPAssumeGlobal.push_back(AA);
3727 auto *Ctx =
SemaRef.CurContext;
3728 while (Ctx->getLexicalParent())
3729 Ctx = Ctx->getLexicalParent();
3730 DeclContexts.push_back(Ctx);
3731 while (!DeclContexts.empty()) {
3733 for (
auto *SubDC : DC->
decls()) {
3734 if (SubDC->isInvalidDecl())
3736 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3737 DeclContexts.push_back(CTD->getTemplatedDecl());
3738 llvm::append_range(DeclContexts, CTD->specializations());
3741 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3742 DeclContexts.push_back(DC);
3743 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3753 OMPAssumeScoped.pop_back();
3774 DSAStack->getEncounteredTargetLocs();
3776 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3777 for (
const OMPClause *CNew : ClauseList) {
3783 Diag(Loc, diag::err_omp_directive_before_requires)
3786 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3791 Diag(Loc, diag::err_omp_directive_before_requires)
3793 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3799 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3807 const DSAStackTy::DSAVarData &DVar,
3808 bool IsLoopIterVar) {
3810 SemaRef.
Diag(DVar.RefExpr->
getExprLoc(), diag::note_omp_explicit_dsa)
3815 PDSA_StaticMemberShared,
3816 PDSA_StaticLocalVarShared,
3817 PDSA_LoopIterVarPrivate,
3818 PDSA_LoopIterVarLinear,
3819 PDSA_LoopIterVarLastprivate,
3820 PDSA_ConstVarShared,
3821 PDSA_GlobalVarShared,
3822 PDSA_TaskVarFirstprivate,
3823 PDSA_LocalVarPrivate,
3825 } Reason = PDSA_Implicit;
3826 bool ReportHint =
false;
3828 auto *VD = dyn_cast<VarDecl>(D);
3829 if (IsLoopIterVar) {
3830 if (DVar.CKind == OMPC_private)
3831 Reason = PDSA_LoopIterVarPrivate;
3832 else if (DVar.CKind == OMPC_lastprivate)
3833 Reason = PDSA_LoopIterVarLastprivate;
3835 Reason = PDSA_LoopIterVarLinear;
3837 DVar.CKind == OMPC_firstprivate) {
3838 Reason = PDSA_TaskVarFirstprivate;
3839 ReportLoc = DVar.ImplicitDSALoc;
3841 Reason = PDSA_StaticLocalVarShared;
3843 Reason = PDSA_StaticMemberShared;
3845 Reason = PDSA_GlobalVarShared;
3847 Reason = PDSA_ConstVarShared;
3848 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3850 Reason = PDSA_LocalVarPrivate;
3852 if (Reason != PDSA_Implicit) {
3853 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
3854 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3855 << Reason << ReportHint
3856 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3857 }
else if (DVar.ImplicitDSALoc.
isValid()) {
3858 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3865 bool IsAggregateOrDeclareTarget,
3866 bool HasConstQualifier) {
3869 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3870 case OMPC_DEFAULTMAP_MODIFIER_storage:
3871 Kind = OMPC_MAP_alloc;
3873 case OMPC_DEFAULTMAP_MODIFIER_to:
3876 case OMPC_DEFAULTMAP_MODIFIER_from:
3877 Kind = OMPC_MAP_from;
3879 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3880 Kind = OMPC_MAP_tofrom;
3882 case OMPC_DEFAULTMAP_MODIFIER_present:
3888 Kind = OMPC_MAP_alloc;
3890 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3891 case OMPC_DEFAULTMAP_MODIFIER_private:
3893 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3894 case OMPC_DEFAULTMAP_MODIFIER_none:
3895 case OMPC_DEFAULTMAP_MODIFIER_default:
3900 if (IsAggregateOrDeclareTarget) {
3901 if (HasConstQualifier)
3904 Kind = OMPC_MAP_tofrom;
3907 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3914 for (
const auto *FD : RD->
fields()) {
3928 while (T->isArrayType())
3929 T = T->getAsArrayTypeUnsafe()->getElementType();
3930 if (!T.isConstQualified())
3932 if (
const auto *RD = T->getAsCXXRecordDecl())
3944struct VariableImplicitInfo {
3949 llvm::SetVector<Expr *> Firstprivates;
3950 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3951 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3952 MapModifiers[DefaultmapKindNum];
3955class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3959 bool ErrorFound =
false;
3960 bool TryCaptureCXXThisMembers =
false;
3961 CapturedStmt *CS =
nullptr;
3963 VariableImplicitInfo ImpInfo;
3965 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3967 void VisitSubCaptures(OMPExecutableDirective *S) {
3969 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3971 if (S->getDirectiveKind() == OMPD_atomic ||
3972 S->getDirectiveKind() == OMPD_critical ||
3973 S->getDirectiveKind() == OMPD_section ||
3974 S->getDirectiveKind() == OMPD_master ||
3975 S->getDirectiveKind() == OMPD_masked ||
3976 S->getDirectiveKind() == OMPD_scope ||
3977 S->getDirectiveKind() == OMPD_assume ||
3979 Visit(S->getAssociatedStmt());
3982 visitSubCaptures(S->getInnermostCapturedStmt());
3985 if (TryCaptureCXXThisMembers ||
3987 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3988 [](
const CapturedStmt::Capture &
C) {
3989 return C.capturesThis();
3991 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3992 TryCaptureCXXThisMembers =
true;
3993 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3994 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
4000 for (OMPClause *
C : S->clauses())
4001 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
4002 for (Expr *Ref : FC->varlist())
4009 void VisitDeclRefExpr(DeclRefExpr *E) {
4015 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
4018 !Stack->getTopDSA(VD,
false).RefExpr &&
4019 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
4020 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
4021 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
4022 Visit(CED->getInit());
4028 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
4033 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4034 !Stack->isImplicitTaskFirstprivate(VD))
4037 if (Stack->isUsesAllocatorsDecl(VD))
4040 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
4042 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
4046 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4047 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4049 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4050 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4051 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4052 !Stack->isImplicitTaskFirstprivate(VD))
4060 if (DVar.CKind == OMPC_unknown &&
4061 (Stack->getDefaultDSA() == DSA_none ||
4062 Stack->getDefaultDSA() == DSA_private ||
4063 Stack->getDefaultDSA() == DSA_firstprivate) &&
4064 isImplicitOrExplicitTaskingRegion(DKind) &&
4065 VarsWithInheritedDSA.count(VD) == 0) {
4066 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4067 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4068 Stack->getDefaultDSA() == DSA_private)) {
4069 DSAStackTy::DSAVarData DVar =
4070 Stack->getImplicitDSA(VD,
false);
4071 InheritedDSA = DVar.CKind == OMPC_unknown;
4074 VarsWithInheritedDSA[VD] = E;
4075 if (Stack->getDefaultDSA() == DSA_none)
4090 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4091 OMPC_DEFAULTMAP_MODIFIER_none;
4092 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4093 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4097 if (!Stack->checkMappableExprComponentListsForDecl(
4102 auto MI = MapExprComponents.rbegin();
4103 auto ME = MapExprComponents.rend();
4104 return MI != ME && MI->getAssociatedDeclaration() == VD;
4106 VarsWithInheritedDSA[VD] = E;
4112 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4113 OMPC_DEFAULTMAP_MODIFIER_present;
4114 if (IsModifierPresent) {
4115 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4116 OMPC_MAP_MODIFIER_present)) {
4117 ImpInfo.MapModifiers[ClauseKind].push_back(
4118 OMPC_MAP_MODIFIER_present);
4124 !Stack->isLoopControlVariable(VD).first) {
4125 if (!Stack->checkMappableExprComponentListsForDecl(
4130 if (SemaRef.LangOpts.OpenMP >= 50)
4131 return !StackComponents.empty();
4134 return StackComponents.size() == 1 ||
4136 llvm::drop_begin(llvm::reverse(StackComponents)),
4137 [](const OMPClauseMappableExprCommon::
4138 MappableComponent &MC) {
4139 return MC.getAssociatedDeclaration() ==
4141 (isa<ArraySectionExpr>(
4142 MC.getAssociatedExpression()) ||
4143 isa<OMPArrayShapingExpr>(
4144 MC.getAssociatedExpression()) ||
4145 isa<ArraySubscriptExpr>(
4146 MC.getAssociatedExpression()));
4149 bool IsFirstprivate =
false;
4151 if (
const auto *RD =
4153 IsFirstprivate = RD->isLambda();
4155 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4156 if (IsFirstprivate) {
4157 ImpInfo.Firstprivates.insert(E);
4160 Stack->getDefaultmapModifier(ClauseKind);
4161 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4162 ImpInfo.Privates.insert(E);
4165 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
4167 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4178 DVar = Stack->hasInnermostDSA(
4181 return C == OMPC_reduction && !AppliedToPointee;
4190 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4196 DVar = Stack->getImplicitDSA(VD,
false);
4198 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4199 DVar.CKind == OMPC_firstprivate) ||
4200 (Stack->getDefaultDSA() == DSA_private &&
4201 DVar.CKind == OMPC_private)) &&
4203 !Stack->isLoopControlVariable(VD).first) {
4204 if (Stack->getDefaultDSA() == DSA_private)
4205 ImpInfo.Privates.insert(E);
4207 ImpInfo.Firstprivates.insert(E);
4214 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4215 Stack->addToParentTargetRegionLinkGlobals(E);
4220 void VisitMemberExpr(MemberExpr *E) {
4228 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
4231 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4235 !Stack->isLoopControlVariable(FD).first &&
4236 !Stack->checkMappableExprComponentListsForDecl(
4241 return isa<CXXThisExpr>(
4243 StackComponents.back().getAssociatedExpression())
4255 if (Stack->isClassPreviouslyMapped(TE->getType()))
4259 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4265 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4274 DVar = Stack->hasInnermostDSA(
4277 return C == OMPC_reduction && !AppliedToPointee;
4286 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4292 DVar = Stack->getImplicitDSA(FD,
false);
4294 !Stack->isLoopControlVariable(FD).first) {
4299 if (DVar.CKind != OMPC_unknown)
4300 ImpInfo.Firstprivates.insert(E);
4310 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4311 if (!Stack->checkMappableExprComponentListsForDecl(
4317 auto CCI = CurComponents.rbegin();
4318 auto CCE = CurComponents.rend();
4319 for (const auto &SC : llvm::reverse(StackComponents)) {
4321 if (CCI->getAssociatedExpression()->getStmtClass() !=
4322 SC.getAssociatedExpression()->getStmtClass())
4323 if (!((isa<ArraySectionExpr>(
4324 SC.getAssociatedExpression()) ||
4325 isa<OMPArrayShapingExpr>(
4326 SC.getAssociatedExpression())) &&
4327 isa<ArraySubscriptExpr>(
4328 CCI->getAssociatedExpression())))
4331 const Decl *CCD = CCI->getAssociatedDeclaration();
4332 const Decl *SCD = SC.getAssociatedDeclaration();
4333 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4334 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4337 std::advance(CCI, 1);
4345 }
else if (!TryCaptureCXXThisMembers) {
4349 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4350 for (OMPClause *
C : S->clauses()) {
4353 if (isa_and_nonnull<OMPPrivateClause>(
C))
4361 for (Stmt *CC :
C->children()) {
4368 VisitSubCaptures(S);
4371 void VisitOMPCanonicalLoopNestTransformationDirective(
4372 OMPCanonicalLoopNestTransformationDirective *S) {
4377 void VisitCallExpr(CallExpr *S) {
4386 auto *CI =
Callee->IgnoreParenImpCasts();
4387 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4388 Visit(CE->getBase());
4389 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4393 void VisitStmt(Stmt *S) {
4403 void visitSubCaptures(CapturedStmt *S) {
4404 for (
const CapturedStmt::Capture &Cap : S->
captures()) {
4405 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4407 VarDecl *VD = Cap.getCapturedVar();
4411 Stack->checkMappableExprComponentListsForDecl(
4418 Cap.getLocation(),
true);
4422 bool isErrorFound()
const {
return ErrorFound; }
4423 const VariableImplicitInfo &getImplicitInfo()
const {
return ImpInfo; }
4425 return VarsWithInheritedDSA;
4428 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4429 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4430 DKind = S->getCurrentDirective();
4433 for (DeclRefExpr *E : Stack->getLinkGlobals())
4445 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4447 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4449 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4451 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4453 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4454 Stack->handleConstructTrait(Traits, ScopeEntry);
4457static SmallVector<SemaOpenMP::CapturedParamNameType>
4461 Context.getIntTypeForBitwidth(32, 1).
withConst();
4465 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4466 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4468 if (LoopBoundSharing) {
4470 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4471 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4475 Params.push_back(std::make_pair(StringRef(),
QualType()));
4479static SmallVector<SemaOpenMP::CapturedParamNameType>
4484static SmallVector<SemaOpenMP::CapturedParamNameType>
4494 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4496 std::make_pair(
".global_tid.", KmpInt32Ty),
4497 std::make_pair(
".part_id.", KmpInt32PtrTy),
4498 std::make_pair(
".privates.", VoidPtrTy),
4501 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4502 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4503 std::make_pair(StringRef(),
QualType())
4508static SmallVector<SemaOpenMP::CapturedParamNameType>
4513 Params.push_back(std::make_pair(StringRef(),
QualType()));
4517 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4521static SmallVector<SemaOpenMP::CapturedParamNameType>
4524 std::make_pair(StringRef(),
QualType())
4529static SmallVector<SemaOpenMP::CapturedParamNameType>
4533 Context.getIntTypeForBitwidth(32, 1).
withConst();
4535 Context.getIntTypeForBitwidth(64, 0).
withConst();
4537 Context.getIntTypeForBitwidth(64, 1).
withConst();
4544 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4546 std::make_pair(
".global_tid.", KmpInt32Ty),
4547 std::make_pair(
".part_id.", KmpInt32PtrTy),
4548 std::make_pair(
".privates.", VoidPtrTy),
4551 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4552 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4553 std::make_pair(
".lb.", KmpUInt64Ty),
4554 std::make_pair(
".ub.", KmpUInt64Ty),
4555 std::make_pair(
".st.", KmpInt64Ty),
4556 std::make_pair(
".liter.", KmpInt32Ty),
4557 std::make_pair(
".reductions.", VoidPtrTy),
4558 std::make_pair(StringRef(),
QualType())
4571 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4572 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4575 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4610 case OMPD_metadirective:
4613 llvm_unreachable(
"Unexpected capture region");
4631 case OMPD_interchange:
4645int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4646 return getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
4652 return CaptureRegions.size();
4656 Expr *CaptureExpr,
bool WithInit,
4658 bool AsExpression) {
4659 assert(CaptureExpr);
4665 Ty =
C.getLValueReferenceType(Ty);
4667 Ty =
C.getPointerType(Ty);
4679 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4729class CaptureRegionUnwinderRAII {
4736 CaptureRegionUnwinderRAII(Sema &S,
bool &ErrorFound,
4738 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4739 ~CaptureRegionUnwinderRAII() {
4742 while (--ThisCaptureLevel >= 0)
4752 if (!
SemaRef.CurContext->isDependentContext() &&
4755 DSAStack->getCurrentDirective()))) {
4757 if (
const auto *RD =
Type.getCanonicalType()
4758 .getNonReferenceType()
4760 bool SavedForceCaptureByReferenceInTargetExecutable =
4761 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4762 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4764 if (RD->isLambda()) {
4765 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4767 RD->getCaptureFields(Captures, ThisCapture);
4774 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4775 }
else if (LC.getCaptureKind() ==
LCK_This) {
4778 ThisTy, ThisCapture->
getType()))
4779 SemaRef.CheckCXXThisCapture(LC.getLocation());
4783 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4784 SavedForceCaptureByReferenceInTargetExecutable);
4791 const OMPOrderedClause *Ordered =
nullptr;
4794 for (
const OMPClause *Clause : Clauses) {
4795 if (Clause->getClauseKind() == OMPC_ordered)
4797 else if (Clause->getClauseKind() == OMPC_order) {
4799 if (Order->
getKind() != OMPC_ORDER_concurrent)
4802 if (Ordered && Order)
4806 if (Ordered && Order) {
4808 diag::err_omp_simple_clause_incompatible_with_ordered)
4811 <<
SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4812 S.
Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4813 << 0 <<
SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4826 bool ErrorFound =
false;
4827 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4836 OMPOrderedClause *OC =
nullptr;
4837 OMPScheduleClause *SC =
nullptr;
4844 DSAStack->getCurrentDirective() == OMPD_target) &&
4845 Clause->getClauseKind() == OMPC_in_reduction) {
4849 for (
Expr *E : IRC->taskgroup_descriptors())
4851 SemaRef.MarkDeclarationsReferencedInExpr(E);
4854 Clause->getClauseKind() == OMPC_copyprivate ||
4857 Clause->getClauseKind() == OMPC_copyin)) {
4858 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4861 if (
auto *E = cast_or_null<Expr>(VarRef)) {
4862 SemaRef.MarkDeclarationsReferencedInExpr(E);
4865 DSAStack->setForceVarCapturing(
false);
4866 }
else if (CaptureRegions.size() > 1 ||
4867 CaptureRegions.back() != OMPD_unknown) {
4871 if (
Expr *E =
C->getPostUpdateExpr())
4872 SemaRef.MarkDeclarationsReferencedInExpr(E);
4875 if (Clause->getClauseKind() == OMPC_schedule)
4877 else if (Clause->getClauseKind() == OMPC_ordered)
4879 else if (Clause->getClauseKind() == OMPC_linear)
4884 SemaRef.MarkDeclarationsReferencedInExpr(E);
4889 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4890 SC->getSecondScheduleModifier() ==
4891 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4893 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4894 ? SC->getFirstScheduleModifierLoc()
4895 : SC->getSecondScheduleModifierLoc(),
4896 diag::err_omp_simple_clause_incompatible_with_ordered)
4899 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4900 <<
SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4908 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4909 for (
const OMPLinearClause *
C : LCs) {
4910 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4911 <<
SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4917 OC->getNumForLoops()) {
4919 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4920 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(), OMPVersion);
4927 unsigned CompletedRegions = 0;
4932 if (ThisCaptureRegion != OMPD_unknown) {
4940 if (CaptureRegion == ThisCaptureRegion ||
4941 CaptureRegion == OMPD_unknown) {
4942 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4943 for (
Decl *D : DS->decls())
4950 if (ThisCaptureRegion == OMPD_target) {
4954 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4955 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4959 SemaRef.MarkDeclarationsReferencedInExpr(E);
4965 if (ThisCaptureRegion == OMPD_parallel) {
4969 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4970 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4972 for (
Expr *E : RC->copy_array_temps())
4974 SemaRef.MarkDeclarationsReferencedInExpr(E);
4976 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4977 for (
Expr *E : AC->varlist())
4978 SemaRef.MarkDeclarationsReferencedInExpr(E);
4982 if (++CompletedRegions == CaptureRegions.size())
4984 SR =
SemaRef.ActOnCapturedRegionEnd(SR.
get());
4993 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4996 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4997 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
5000 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
5001 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
5002 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
5012 if (!Stack->getCurScope())
5017 bool NestingProhibited =
false;
5018 bool CloseNesting =
true;
5019 bool OrphanSeen =
false;
5022 ShouldBeInParallelRegion,
5023 ShouldBeInOrderedRegion,
5024 ShouldBeInTargetRegion,
5025 ShouldBeInTeamsRegion,
5026 ShouldBeInLoopSimdRegion,
5027 } Recommend = NoRecommend;
5031 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
5033 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
5035 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5038 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
5039 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5043 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
5044 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
5045 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5046 CurrentRegion != OMPD_scan))) {
5059 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
5060 ? diag::err_omp_prohibited_region_simd
5061 : diag::warn_omp_nesting_simd)
5062 << (OMPVersion >= 50 ? 1 : 0);
5063 return CurrentRegion != OMPD_simd;
5065 if (EnclosingConstruct == OMPD_atomic) {
5068 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5071 if (CurrentRegion == OMPD_section) {
5076 if (EnclosingConstruct != OMPD_sections) {
5077 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5078 << (ParentRegion != OMPD_unknown)
5079 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5087 if (ParentRegion == OMPD_unknown &&
5089 CurrentRegion != OMPD_cancellation_point &&
5090 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5094 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5095 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5097 EnclosingConstruct == OMPD_loop)) {
5098 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5099 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5100 <<
true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5101 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5104 if (CurrentRegion == OMPD_cancellation_point ||
5105 CurrentRegion == OMPD_cancel) {
5118 if (CancelRegion == OMPD_taskgroup) {
5120 EnclosingConstruct != OMPD_task &&
5121 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5122 }
else if (CancelRegion == OMPD_sections) {
5123 NestingProhibited = EnclosingConstruct != OMPD_section &&
5124 EnclosingConstruct != OMPD_sections;
5126 NestingProhibited = CancelRegion != Leafs.back();
5128 OrphanSeen = ParentRegion == OMPD_unknown;
5129 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5136 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
5142 bool DeadLock = Stack->hasDirective(
5146 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
5147 PreviousCriticalLoc = Loc;
5154 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5156 if (PreviousCriticalLoc.
isValid())
5157 SemaRef.
Diag(PreviousCriticalLoc,
5158 diag::note_omp_previous_critical_region);
5161 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5171 llvm::is_contained({OMPD_masked, OMPD_master,
5172 OMPD_critical, OMPD_ordered},
5173 EnclosingConstruct);
5184 llvm::is_contained({OMPD_masked, OMPD_master,
5185 OMPD_critical, OMPD_ordered},
5186 EnclosingConstruct);
5187 Recommend = ShouldBeInParallelRegion;
5188 }
else if (CurrentRegion == OMPD_ordered) {
5197 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5200 Stack->isParentOrderedRegion());
5201 Recommend = ShouldBeInOrderedRegion;
5207 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5208 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5209 EnclosingConstruct != OMPD_target);
5210 OrphanSeen = ParentRegion == OMPD_unknown;
5211 Recommend = ShouldBeInTargetRegion;
5212 }
else if (CurrentRegion == OMPD_scan) {
5213 if (OMPVersion >= 50) {
5218 NestingProhibited = !llvm::is_contained(
5219 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5221 NestingProhibited =
true;
5223 OrphanSeen = ParentRegion == OMPD_unknown;
5224 Recommend = ShouldBeInLoopSimdRegion;
5228 EnclosingConstruct == OMPD_teams) {
5240 CurrentRegion != OMPD_loop &&
5242 CurrentRegion == OMPD_atomic);
5243 Recommend = ShouldBeInParallelRegion;
5245 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5251 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5252 Recommend = ShouldBeInTeamsRegion;
5258 NestingProhibited = EnclosingConstruct != OMPD_teams;
5259 Recommend = ShouldBeInTeamsRegion;
5261 if (!NestingProhibited &&
5268 NestingProhibited = Stack->hasDirective(
5272 OffendingRegion = K;
5278 CloseNesting =
false;
5280 if (NestingProhibited) {
5282 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5283 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5285 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5286 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5287 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5301 bool ErrorFound =
false;
5302 unsigned NamedModifiersNumber = 0;
5303 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5304 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5308 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5312 auto &FNM = FoundNameModifiers[CurNM];
5314 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5315 << getOpenMPDirectiveName(Kind, OMPVersion)
5317 << getOpenMPDirectiveName(CurNM, OMPVersion);
5319 }
else if (CurNM != OMPD_unknown) {
5320 NameModifierLoc.push_back(IC->getNameModifierLoc());
5321 ++NamedModifiersNumber;
5324 if (CurNM == OMPD_unknown)
5330 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5331 S.
Diag(IC->getNameModifierLoc(),
5332 diag::err_omp_wrong_if_directive_name_modifier)
5333 << getOpenMPDirectiveName(CurNM, OMPVersion)
5334 << getOpenMPDirectiveName(Kind, OMPVersion);
5341 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5342 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5343 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5344 diag::err_omp_no_more_if_clause);
5347 std::string Sep(
", ");
5348 unsigned AllowedCnt = 0;
5349 unsigned TotalAllowedNum =
5350 AllowedNameModifiers.size() - NamedModifiersNumber;
5351 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5354 if (!FoundNameModifiers[NM]) {
5356 Values += getOpenMPDirectiveName(NM, OMPVersion);
5358 if (AllowedCnt + 2 == TotalAllowedNum)
5360 else if (AllowedCnt + 1 != TotalAllowedNum)
5365 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5366 diag::err_omp_unnamed_if_clause)
5367 << (TotalAllowedNum > 1) << Values;
5370 S.
Diag(Loc, diag::note_omp_previous_named_if_clause);
5377static std::pair<ValueDecl *, bool>
5380 bool AllowAssumedSizeArray, StringRef DiagType) {
5383 return std::make_pair(
nullptr,
true);
5409 } IsArrayExpr = NoArrayExpr;
5410 if (AllowArraySection) {
5411 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5412 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5413 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5414 Base = TempASE->getBase()->IgnoreParenImpCasts();
5417 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5418 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5419 if (S.
getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5420 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5422 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5423 !BaseType->isVariableArrayType())) {
5424 S.
Diag(OASE->getColonLocFirst(),
5425 diag::err_omp_section_length_undefined)
5426 << (!BaseType.isNull() && BaseType->isArrayType());
5427 return std::make_pair(
nullptr,
false);
5430 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5431 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5432 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5433 Base = TempASE->getBase()->IgnoreParenImpCasts();
5435 IsArrayExpr = OMPArraySection;
5441 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5442 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5447 if (IsArrayExpr != NoArrayExpr) {
5448 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5449 << IsArrayExpr << ERange;
5450 }
else if (!DiagType.empty()) {
5454 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5455 << DiagSelect << DiagType << ERange;
5459 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5460 : diag::err_omp_expected_var_name_member_expr)
5463 return std::make_pair(
nullptr,
false);
5465 return std::make_pair(
5472class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5473 DSAStackTy *S =
nullptr;
5476 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
5477 return S->isUsesAllocatorsDecl(E->
getDecl())
5478 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5479 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5481 bool VisitStmt(
const Stmt *S) {
5482 for (
const Stmt *Child : S->
children()) {
5483 if (Child && Visit(Child))
5488 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5495 "Expected non-dependent context.");
5496 auto AllocateRange =
5499 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5504 if (
Cl->getClauseKind() == OMPC_private) {
5506 I = PC->private_copies().begin();
5507 It = PC->varlist_begin();
5508 Et = PC->varlist_end();
5509 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5511 I = PC->private_copies().begin();
5512 It = PC->varlist_begin();
5513 Et = PC->varlist_end();
5514 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5516 I = PC->private_copies().begin();
5517 It = PC->varlist_begin();
5518 Et = PC->varlist_end();
5519 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5521 I = PC->privates().begin();
5522 It = PC->varlist_begin();
5523 Et = PC->varlist_end();
5524 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5526 I = PC->privates().begin();
5527 It = PC->varlist_begin();
5528 Et = PC->varlist_end();
5529 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5531 I = PC->privates().begin();
5532 It = PC->varlist_begin();
5533 Et = PC->varlist_end();
5534 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5536 I = PC->privates().begin();
5537 It = PC->varlist_begin();
5538 Et = PC->varlist_end();
5540 llvm_unreachable(
"Expected private clause.");
5542 for (
Expr *E : llvm::make_range(It, Et)) {
5549 Expr *SimpleRefExpr = E;
5552 DeclToCopy.try_emplace(Res.first,
5560 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5562 AC->getAllocator()) {
5563 Expr *Allocator = AC->getAllocator();
5569 AllocatorChecker Checker(Stack);
5570 if (Checker.Visit(Allocator))
5572 diag::err_omp_allocator_not_in_uses_allocators)
5575 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5581 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5585 S.
Diag(AC->getAllocator()->getExprLoc(),
5586 diag::warn_omp_allocate_thread_on_task_target_directive)
5587 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5589 for (
Expr *E : AC->varlist()) {
5592 Expr *SimpleRefExpr = E;
5597 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5600 diag::err_omp_expected_private_copy_for_allocate);
5603 VarDecl *PrivateVD = DeclToCopy[VD];
5605 AllocatorKind, AC->getAllocator()))
5619class CaptureVars :
public TreeTransform<CaptureVars> {
5620 using BaseTransform = TreeTransform<CaptureVars>;
5623 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5625 bool AlwaysRebuild() {
return true; }
5638 BodyStmts.push_back(NewDeclStmt);
5676 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5687 auto BuildVarRef = [&](
VarDecl *VD) {
5692 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5694 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5700 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep),
Zero));
5704 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5708 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5712 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5716 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5718 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5722 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5724 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5725 "Expected one of these relational operators");
5732 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5736 if (Rel == BO_GE || Rel == BO_GT)
5738 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5741 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5747 if (Rel == BO_LE || Rel == BO_GE) {
5759 Expr *Divisor = BuildVarRef(NewStep);
5760 if (Rel == BO_GE || Rel == BO_GT)
5763 Expr *DivisorMinusOne =
5766 Actions.
BuildBinOp(
nullptr, {}, BO_Add, Range, DivisorMinusOne));
5768 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5778 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5779 BodyStmts.push_back(ResultAssign);
5811 {
"Logical", LogicalTy},
5822 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5831 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5834 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5837 CaptureVars Recap(Actions);
5842 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5857 BO_Assign, TargetRef, Advanced));
5870 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5872 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5875 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5877 assert(LCAssign->getOpcode() == BO_Assign &&
5878 "init part must be a loop variable assignment");
5882 llvm_unreachable(
"Cannot determine loop variable");
5885 Cond = For->getCond();
5886 Inc = For->getInc();
5887 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5888 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5890 LUVDecl = RangeFor->getLoopVariable();
5892 Cond = RangeFor->getCond();
5893 Inc = RangeFor->getInc();
5895 llvm_unreachable(
"unhandled kind of loop");
5904 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(
Cond)) {
5905 LHS = CondBinExpr->getLHS();
5906 RHS = CondBinExpr->getRHS();
5907 CondRel = CondBinExpr->getOpcode();
5908 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(
Cond)) {
5909 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5910 LHS = CondCXXOp->getArg(0);
5911 RHS = CondCXXOp->getArg(1);
5912 switch (CondCXXOp->getOperator()) {
5913 case OO_ExclaimEqual:
5925 case OO_GreaterEqual:
5929 llvm_unreachable(
"unexpected iterator operator");
5932 llvm_unreachable(
"unexpected loop condition");
5937 std::swap(LHS, RHS);
5954 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5956 switch (IncUn->getOpcode()) {
5966 llvm_unreachable(
"unhandled unary increment operator");
5970 llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction,
true),
5972 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5973 if (IncBin->getOpcode() == BO_AddAssign) {
5974 Step = IncBin->getRHS();
5975 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5977 SemaRef.BuildUnaryOp(
nullptr, {}, UO_Minus, IncBin->getRHS()));
5979 llvm_unreachable(
"unhandled binary increment operator");
5980 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5981 switch (CondCXXOp->getOperator()) {
5984 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5988 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5991 Step = CondCXXOp->getArg(1);
5995 SemaRef.BuildUnaryOp(
nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5998 llvm_unreachable(
"unhandled overloaded increment operator");
6001 llvm_unreachable(
"unknown increment expression");
6009 nullptr,
nullptr, {},
nullptr);
6010 return OMPCanonicalLoop::create(
getASTContext(), AStmt, DistanceFunc,
6011 LoopVarFunc, LVRef);
6023 "Loop transformation directive expected");
6024 return LoopTransform;
6031 Expr *UnresolvedMapper);
6042 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6043 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6047 auto *MI =
C->mapperlist_begin();
6048 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
6067 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6068 ElemType = ATy->getElementType();
6071 CanonType = ElemType;
6076 1, {CanonType,
nullptr});
6077 llvm::DenseMap<const Type *, Expr *> Visited;
6080 while (!Types.empty()) {
6083 std::tie(BaseType, CurFD) = Types.pop_back_val();
6084 while (ParentChain.back().second == 0)
6085 ParentChain.pop_back();
6086 --ParentChain.back().second;
6087 if (BaseType.isNull())
6090 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6093 auto It = Visited.find(BaseType.getTypePtr());
6094 if (It == Visited.end()) {
6102 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6106 It = Visited.try_emplace(BaseType.getTypePtr(), ER.
get()).first;
6113 Expr *BaseExpr = OE;
6114 for (
const auto &P : ParentChain) {
6132 SubExprs.push_back(BaseExpr);
6136 bool FirstIter =
true;
6146 ParentChain.emplace_back(CurFD, 1);
6148 ++ParentChain.back().second;
6150 Types.emplace_back(FieldTy, FD);
6154 if (SubExprs.empty())
6159 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
6160 MapperIdScopeSpec, MapperId,
C->getMapType(),
6163 Clauses.push_back(NewClause);
6170class TeamsLoopChecker final :
public ConstStmtVisitor<TeamsLoopChecker> {
6177 void VisitOMPExecutableDirective(
const OMPExecutableDirective *D) {
6178 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6179 if (
const auto *
C = D->getSingleClause<OMPBindClause>())
6180 if (
C->getBindKind() == OMPC_BIND_parallel) {
6181 TeamsLoopCanBeParallelFor =
false;
6186 for (
const Stmt *Child : D->children())
6191 void VisitCallExpr(
const CallExpr *
C) {
6196 bool IsOpenMPAPI =
false;
6197 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
6199 std::string Name = FD->getNameInfo().getAsString();
6200 IsOpenMPAPI = Name.find(
"omp_") == 0;
6202 TeamsLoopCanBeParallelFor =
6203 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6204 if (!TeamsLoopCanBeParallelFor)
6207 for (
const Stmt *Child :
C->children())
6212 void VisitCapturedStmt(
const CapturedStmt *S) {
6218 void VisitStmt(
const Stmt *S) {
6221 for (
const Stmt *Child : S->
children())
6225 explicit TeamsLoopChecker(Sema &SemaRef)
6226 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
6229 bool TeamsLoopCanBeParallelFor;
6234 TeamsLoopChecker Checker(SemaRef);
6235 Checker.Visit(AStmt);
6236 return Checker.teamsLoopCanBeParallelFor();
6250 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6251 BindKind = BC->getBindKind();
6263 BindKind = OMPC_BIND_thread;
6265 getLeafConstructsOrSelf(ParentDirective);
6267 if (ParentDirective == OMPD_unknown) {
6269 diag::err_omp_bind_required_on_loop);
6270 }
else if (ParentLeafs.back() == OMPD_parallel) {
6271 BindKind = OMPC_BIND_parallel;
6272 }
else if (ParentLeafs.back() == OMPD_teams) {
6273 BindKind = OMPC_BIND_teams;
6281 ClausesWithImplicit.push_back(
C);
6285 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6287 if (
C->getClauseKind() == OMPC_reduction)
6289 diag::err_omp_loop_reduction_clause);
6296 BindKind, StartLoc)) {
6303 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6306 bool ErrorFound =
false;
6307 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6309 if (AStmt && !
SemaRef.CurContext->isDependentContext() &&
6317 while (--ThisCaptureLevel >= 0)
6319 DSAChecker.Visit(S);
6327 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6329 DSAChecker.visitSubCaptures(CS);
6331 if (DSAChecker.isErrorFound())
6334 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6335 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6338 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6340 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6342 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6343 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6344 PresentModifierLocs[DMC->getDefaultmapKind()] =
6345 DMC->getDefaultmapModifierLoc();
6349 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6351 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6352 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6356 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6357 for (
Expr *E : IRC->taskgroup_descriptors())
6359 ImpInfo.Firstprivates.insert(E);
6364 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6365 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6367 if (!ImpInfo.Firstprivates.empty()) {
6371 ClausesWithImplicit.push_back(
Implicit);
6373 ImpInfo.Firstprivates.size();
6378 if (!ImpInfo.Privates.empty()) {
6382 ClausesWithImplicit.push_back(
Implicit);
6384 ImpInfo.Privates.size();
6393 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6397 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6398 for (
Expr *E : RC->varlist())
6400 ImplicitExprs.emplace_back(E);
6402 if (!ImplicitExprs.empty()) {
6408 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6411 ClausesWithImplicit.emplace_back(
Implicit);
6414 for (
unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6415 int ClauseKindCnt = -1;
6416 for (
unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6419 if (ImplicitMap.empty())
6425 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6426 MapperIdScopeSpec, MapperId, K,
true,
6429 ClausesWithImplicit.emplace_back(
Implicit);
6441 ClausesWithImplicit);
6451 VarsWithInheritedDSA);
6466 assert(ClausesWithImplicit.empty() &&
6467 "reverse directive does not support any clauses");
6474 case OMPD_interchange:
6484 VarsWithInheritedDSA);
6488 EndLoc, VarsWithInheritedDSA);
6495 assert(ClausesWithImplicit.empty() &&
6496 "No clauses are allowed for 'omp section' directive");
6504 assert(ClausesWithImplicit.empty() &&
6505 "No clauses are allowed for 'omp master' directive");
6516 case OMPD_parallel_for:
6518 EndLoc, VarsWithInheritedDSA);
6520 case OMPD_parallel_for_simd:
6522 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6528 case OMPD_parallel_master:
6532 case OMPD_parallel_masked:
6536 case OMPD_parallel_sections:
6544 case OMPD_taskyield:
6545 assert(ClausesWithImplicit.empty() &&
6546 "No clauses are allowed for 'omp taskyield' directive");
6547 assert(AStmt ==
nullptr &&
6548 "No associated statement allowed for 'omp taskyield' directive");
6552 assert(AStmt ==
nullptr &&
6553 "No associated statement allowed for 'omp error' directive");
6557 assert(ClausesWithImplicit.empty() &&
6558 "No clauses are allowed for 'omp barrier' directive");
6559 assert(AStmt ==
nullptr &&
6560 "No associated statement allowed for 'omp barrier' directive");
6564 assert(AStmt ==
nullptr &&
6565 "No associated statement allowed for 'omp taskwait' directive");
6568 case OMPD_taskgroup:
6573 assert(AStmt ==
nullptr &&
6574 "No associated statement allowed for 'omp flush' directive");
6578 assert(AStmt ==
nullptr &&
6579 "No associated statement allowed for 'omp depobj' directive");
6583 assert(AStmt ==
nullptr &&
6584 "No associated statement allowed for 'omp scan' directive");
6603 case OMPD_target_parallel:
6607 case OMPD_target_parallel_for:
6609 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6611 case OMPD_cancellation_point:
6612 assert(ClausesWithImplicit.empty() &&
6613 "No clauses are allowed for 'omp cancellation point' directive");
6614 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6615 "cancellation point' directive");
6619 assert(AStmt ==
nullptr &&
6620 "No associated statement allowed for 'omp cancel' directive");
6624 case OMPD_target_data:
6628 case OMPD_target_enter_data:
6632 case OMPD_target_exit_data:
6638 EndLoc, VarsWithInheritedDSA);
6640 case OMPD_taskloop_simd:
6642 EndLoc, VarsWithInheritedDSA);
6644 case OMPD_master_taskloop:
6646 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6648 case OMPD_masked_taskloop:
6650 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6652 case OMPD_master_taskloop_simd:
6654 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6656 case OMPD_masked_taskloop_simd:
6658 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6660 case OMPD_parallel_master_taskloop:
6662 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6664 case OMPD_parallel_masked_taskloop:
6666 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6668 case OMPD_parallel_master_taskloop_simd:
6670 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6672 case OMPD_parallel_masked_taskloop_simd:
6674 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6676 case OMPD_distribute:
6678 EndLoc, VarsWithInheritedDSA);
6680 case OMPD_target_update:
6684 case OMPD_distribute_parallel_for:
6686 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6688 case OMPD_distribute_parallel_for_simd:
6690 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6692 case OMPD_distribute_simd:
6694 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6696 case OMPD_target_parallel_for_simd:
6698 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6700 case OMPD_target_simd:
6702 EndLoc, VarsWithInheritedDSA);
6704 case OMPD_teams_distribute:
6706 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6708 case OMPD_teams_distribute_simd:
6710 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6712 case OMPD_teams_distribute_parallel_for_simd:
6714 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6716 case OMPD_teams_distribute_parallel_for:
6718 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6720 case OMPD_target_teams:
6724 case OMPD_target_teams_distribute:
6726 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6728 case OMPD_target_teams_distribute_parallel_for:
6730 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6732 case OMPD_target_teams_distribute_parallel_for_simd:
6734 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6736 case OMPD_target_teams_distribute_simd:
6738 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6741 assert(AStmt ==
nullptr &&
6742 "No associated statement allowed for 'omp interop' directive");
6751 EndLoc, VarsWithInheritedDSA);
6753 case OMPD_teams_loop:
6755 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6757 case OMPD_target_teams_loop:
6759 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6761 case OMPD_parallel_loop:
6763 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6765 case OMPD_target_parallel_loop:
6767 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6769 case OMPD_declare_target:
6770 case OMPD_end_declare_target:
6771 case OMPD_threadprivate:
6773 case OMPD_declare_reduction:
6774 case OMPD_declare_mapper:
6775 case OMPD_declare_simd:
6777 case OMPD_declare_variant:
6778 case OMPD_begin_declare_variant:
6779 case OMPD_end_declare_variant:
6780 llvm_unreachable(
"OpenMP Directive is not allowed");
6781 case OMPD_taskgraph:
6782 Diag(StartLoc, diag::err_omp_unexpected_directive)
6783 << 1 << getOpenMPDirectiveName(OMPD_taskgraph);
6787 llvm_unreachable(
"Unknown OpenMP directive");
6790 ErrorFound = Res.
isInvalid() || ErrorFound;
6794 if (
DSAStack->getDefaultDSA() == DSA_none ||
6795 DSAStack->getDefaultDSA() == DSA_private ||
6796 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6799 switch (
C->getClauseKind()) {
6800 case OMPC_num_threads:
6801 case OMPC_dist_schedule:
6818 case OMPC_grainsize:
6819 case OMPC_num_tasks:
6822 case OMPC_novariants:
6823 case OMPC_nocontext:
6830 case OMPC_num_teams:
6831 case OMPC_thread_limit:
6838 case OMPC_proc_bind:
6840 case OMPC_firstprivate:
6841 case OMPC_lastprivate:
6843 case OMPC_reduction:
6844 case OMPC_task_reduction:
6845 case OMPC_in_reduction:
6849 case OMPC_copyprivate:
6852 case OMPC_mergeable:
6869 case OMPC_defaultmap:
6872 case OMPC_use_device_ptr:
6873 case OMPC_use_device_addr:
6874 case OMPC_is_device_ptr:
6875 case OMPC_has_device_addr:
6876 case OMPC_nontemporal:
6879 case OMPC_inclusive:
6880 case OMPC_exclusive:
6881 case OMPC_uses_allocators:
6888 case OMPC_allocator:
6891 case OMPC_threadprivate:
6892 case OMPC_groupprivate:
6895 case OMPC_unified_address:
6896 case OMPC_unified_shared_memory:
6897 case OMPC_reverse_offload:
6898 case OMPC_dynamic_allocators:
6899 case OMPC_atomic_default_mem_order:
6900 case OMPC_self_maps:
6901 case OMPC_device_type:
6906 llvm_unreachable(
"Unexpected clause");
6908 for (
Stmt *CC :
C->children()) {
6910 DSAChecker.Visit(CC);
6913 for (
const auto &P : DSAChecker.getVarsWithInheritedDSA())
6914 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6916 for (
const auto &P : VarsWithInheritedDSA) {
6920 if (
DSAStack->getDefaultDSA() == DSA_none ||
6921 DSAStack->getDefaultDSA() == DSA_private ||
6922 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6923 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6924 << P.first << P.second->getSourceRange();
6925 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6927 Diag(P.second->getExprLoc(),
6928 diag::err_omp_defaultmap_no_attr_for_variable)
6929 << P.first << P.second->getSourceRange();
6931 diag::note_omp_defaultmap_attr_none);
6937 if (isAllowedClauseForDirective(D, OMPC_if,
getLangOpts().OpenMP))
6938 AllowedNameModifiers.push_back(D);
6940 if (!AllowedNameModifiers.empty())
6947 if (!
SemaRef.CurContext->isDependentContext() &&
6949 !(
DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6950 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6951 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6952 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6954 DSAStack->addTargetDirLocation(StartLoc);
6965 assert(Aligneds.size() == Alignments.size());
6966 assert(Linears.size() == LinModifiers.size());
6967 assert(Linears.size() == Steps.size());
6971 const int SimdId = 0;
6973 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6978 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6979 ADecl = FTD->getTemplatedDecl();
6981 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6983 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6999 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7000 const Expr *UniformedLinearThis =
nullptr;
7001 for (
const Expr *E : Uniforms) {
7003 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7004 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
7005 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7006 FD->getParamDecl(PVD->getFunctionScopeIndex())
7008 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7012 UniformedLinearThis = E;
7026 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7027 const Expr *AlignedThis =
nullptr;
7028 for (
const Expr *E : Aligneds) {
7030 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7031 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7033 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7034 FD->getParamDecl(PVD->getFunctionScopeIndex())
7038 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
7043 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7048 .getNonReferenceType()
7049 .getUnqualifiedType()
7050 .getCanonicalType();
7053 Diag(E->
getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7055 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7079 for (
Expr *E : Alignments) {
7083 NewAligns.push_back(Align.
get());
7094 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7095 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
7096 auto MI = LinModifiers.begin();
7097 for (
const Expr *E : Linears) {
7101 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7102 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7104 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7105 FD->getParamDecl(PVD->getFunctionScopeIndex())
7109 if (
auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7114 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7119 if (
auto It = UniformedArgs.find(CanonPVD);
7120 It != UniformedArgs.end()) {
7125 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7129 LinearArgs[CanonPVD] = E;
7135 PVD->getOriginalType(),
7141 if (UniformedLinearThis) {
7147 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
7152 UniformedLinearThis = E;
7163 Expr *Step =
nullptr;
7164 Expr *NewStep =
nullptr;
7166 for (
Expr *E : Steps) {
7168 if (Step == E || !E) {
7169 NewSteps.push_back(E ? NewStep :
nullptr);
7173 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7174 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7176 if (UniformedArgs.count(CanonPVD) == 0) {
7183 NewSteps.push_back(Step);
7198 .VerifyIntegerConstantExpression(
7202 NewSteps.push_back(NewStep);
7204 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7206 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
7207 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
7208 const_cast<Expr **
>(Linears.data()), Linears.size(),
7209 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
7210 NewSteps.data(), NewSteps.size(), SR);
7220 "Unexpected directive category");
7229 llvm_unreachable(
"Unknown OpenMP directive");
7238 "Expected function type with prototype.");
7240 "Expected function with type with no prototype.");
7242 "Expected function with prototype.");
7250 Param->setScopeInfo(0, Params.size());
7251 Param->setImplicit();
7252 Params.push_back(Param);
7255 FD->setParams(Params);
7262 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7263 FD = UTemplDecl->getTemplatedDecl();
7266 assert(FD &&
"Expected a function declaration!");
7271 if (!
SemaRef.inTemplateInstantiation()) {
7272 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7275 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7279SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7280 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7288 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7291 bool IsTemplated = !TemplateParamLists.empty();
7294 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7311 for (
auto *Candidate : Lookup) {
7312 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7317 if (
SemaRef.Context.isSameTemplateParameterList(
7318 FTD->getTemplateParameters(), TemplateParamLists.back()))
7319 UDecl = FTD->getTemplatedDecl();
7320 }
else if (!IsTemplated)
7321 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7335 FType, UDeclTy,
false,
7342 Bases.push_back(UDecl);
7346 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7348 if (Bases.empty() && UseImplicitBase) {
7350 Decl *BaseD =
SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7352 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7353 Bases.push_back(BaseTemplD->getTemplatedDecl());
7358 std::string MangledName;
7361 MangledName += DVScope.NameSuffix;
7376 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7377 FD = UTemplDecl->getTemplatedDecl();
7385 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7386 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7393 BaseFD->addAttr(OMPDeclareVariantA);
7411 if (!CalleeFnDecl) {
7416 if ((DRE = dyn_cast<DeclRefExpr>(E)))
7418 if (
auto *ME = dyn_cast<MemberExpr>(E))
7420 else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
7426 if (VD && !VD->
hasAttr<OMPTargetIndirectCallAttr>()) {
7429 ML->DeclarationMarkedOpenMPIndirectCall(VD);
7438 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7441 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7444 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7449 CE](StringRef ISATrait) {
7463 while (CalleeFnDecl) {
7464 for (OMPDeclareVariantAttr *A :
7466 Expr *VariantRef = A->getVariantFuncRef();
7468 VariantMatchInfo VMI;
7471 if (!isVariantApplicableInContext(VMI, OMPCtx,
7475 VMIs.push_back(VMI);
7476 Exprs.push_back(VariantRef);
7484 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7504 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7505 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7507 Context, MemberCall->getImplicitObjectArgument(),
7508 false, SpecializedMethod, Context.BoundMemberTy,
7509 MemberCall->getValueKind(), MemberCall->getObjectKind());
7511 NewCall =
SemaRef.BuildCallExpr(
Scope, BestExpr, LParenLoc, ArgExprs,
7512 RParenLoc, ExecConfig);
7514 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7515 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7517 CalleeFnType, NewCalleeFnDecl->
getType(),
7528 VMIs.erase(VMIs.begin() + BestIdx);
7529 Exprs.erase(Exprs.begin() + BestIdx);
7530 }
while (!VMIs.empty());
7537std::optional<std::pair<FunctionDecl *, Expr *>>
7541 unsigned NumAppendArgs,
7545 return std::nullopt;
7547 const int VariantId = 1;
7550 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7552 return std::nullopt;
7555 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7556 ADecl = FTD->getTemplatedDecl();
7559 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7563 return std::nullopt;
7566 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7569 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7572 if (HasMultiVersionAttributes(FD)) {
7573 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7575 return std::nullopt;
7580 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7585 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7587 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7592 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7593 return std::nullopt;
7596 auto ShouldDelayChecks = [](
Expr *&E, bool) {
7602 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7604 return std::make_pair(FD, VariantRef);
7607 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&E,
7608 bool IsScore) ->
bool {
7614 Diag(E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7622 diag::err_omp_declare_variant_user_condition_not_constant)
7628 return std::nullopt;
7631 if (NumAppendArgs) {
7634 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7636 return std::nullopt;
7645 TD = dyn_cast_or_null<TypeDecl>(ND);
7648 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7649 return std::nullopt;
7654 if (PTy->isVariadic()) {
7655 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7656 return std::nullopt;
7659 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7660 Params.insert(Params.end(), NumAppendArgs, InteropType);
7661 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7662 PTy->getExtProtoInfo());
7670 auto *
Method = dyn_cast<CXXMethodDecl>(FD);
7672 FnPtrType = Context.getMemberPointerType(
7673 AdjustedFnType, std::nullopt,
Method->getParent());
7685 return std::nullopt;
7687 VariantRef = ER.
get();
7689 FnPtrType = Context.getPointerType(AdjustedFnType);
7691 QualType VarianPtrType = Context.getPointerType(VariantRef->
getType());
7695 false, Sema::AllowedExplicit::None,
7701 diag::err_omp_declare_variant_incompat_types)
7705 return std::nullopt;
7707 VariantRefCast =
SemaRef.PerformImplicitConversion(
7711 return std::nullopt;
7715 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7716 if (
auto *UO = dyn_cast<UnaryOperator>(
7718 VariantRefCast = UO->getSubExpr();
7727 return std::nullopt;
7735 return std::nullopt;
7737 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7741 return std::nullopt;
7746 diag::err_omp_declare_variant_same_base_function)
7748 return std::nullopt;
7754 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7757 diag::err_omp_declare_variant_incompat_types)
7758 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7760 return std::nullopt;
7765 else if (NewFD->getType()->isFunctionNoProtoType())
7771 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7773 diag::warn_omp_declare_variant_marked_as_declare_variant)
7776 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7777 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7778 return std::nullopt;
7781 enum DoesntSupport {
7790 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7791 if (CXXFD->isVirtual()) {
7794 return std::nullopt;
7800 return std::nullopt;
7806 return std::nullopt;
7810 if (FD->isDeleted()) {
7813 return std::nullopt;
7816 if (FD->isDefaulted()) {
7819 return std::nullopt;
7822 if (FD->isConstexpr()) {
7824 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7825 return std::nullopt;
7829 if (
SemaRef.areMultiversionVariantFunctionsCompatible(
7835 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7837 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7841 return std::nullopt;
7859 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7860 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7861 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7863 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7864 VariantMatchInfo VMI;
7866 if (!llvm::is_contained(
7867 VMI.ConstructTraits,
7868 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7869 if (!AllAdjustArgs.empty())
7870 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7872 if (!AppendArgs.empty())
7873 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7884 for (
Expr *E : AllAdjustArgs) {
7886 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7887 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7889 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7893 if (!AdjustVars.insert(CanonPVD).second) {
7894 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7903 Diag(E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7912 for (
Expr *E : AdjustArgsNeedDeviceAddr) {
7914 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7915 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7918 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7924 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7926 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7927 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7928 AdjustArgsNeedDevicePtr.size(),
7929 const_cast<Expr **
>(AdjustArgsNeedDeviceAddr.data()),
7930 AdjustArgsNeedDeviceAddr.size(),
7931 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7937 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7938 assert(CS &&
"Captured statement expected");
7947 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7969 return OMPParallelDirective::Create(
7976struct LoopIterationSpace final {
7979 bool IsStrictCompare =
false;
7981 Expr *PreCond =
nullptr;
7984 Expr *NumIterations =
nullptr;
7986 Expr *CounterVar =
nullptr;
7988 Expr *PrivateCounterVar =
nullptr;
7990 Expr *CounterInit =
nullptr;
7993 Expr *CounterStep =
nullptr;
7995 bool Subtract =
false;
8005 Expr *MinValue =
nullptr;
8009 Expr *MaxValue =
nullptr;
8011 bool IsNonRectangularLB =
false;
8013 bool IsNonRectangularUB =
false;
8016 unsigned LoopDependentIdx = 0;
8020 Expr *FinalCondition =
nullptr;
8027 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8028 VarDecl *ForbiddenVar =
nullptr;
8032 explicit ForSubExprChecker(
8033 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
8034 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
8037 ShouldVisitImplicitCode =
true;
8040 bool VisitDeclRefExpr(DeclRefExpr *E)
override {
8045 if (
V->getType()->isReferenceType()) {
8046 VarDecl *VD =
V->getDefinition();
8049 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
8055 Decl *Canon =
V->getCanonicalDecl();
8056 if (CollapsedLoopVarDecls.contains(Canon)) {
8065 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
8066 SourceRange getErrRange()
const {
return ErrLoc; }
8072class OpenMPIterationSpaceChecker {
8076 bool SupportsNonRectangular;
8080 SourceLocation DefaultLoc;
8082 SourceLocation ConditionLoc;
8084 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8086 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars;
8088 SourceRange InitSrcRange;
8090 SourceRange ConditionSrcRange;
8092 SourceRange IncrementSrcRange;
8094 ValueDecl *LCDecl =
nullptr;
8096 Expr *LCRef =
nullptr;
8102 Expr *Step =
nullptr;
8109 std::optional<bool> TestIsLessOp;
8111 bool TestIsStrictOp =
false;
8113 bool SubtractStep =
false;
8115 const ValueDecl *DepDecl =
nullptr;
8118 std::optional<unsigned> InitDependOnLC;
8121 std::optional<unsigned> CondDependOnLC;
8123 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
8124 bool IsInitializer);
8130 OpenMPIterationSpaceChecker(
8131 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
8132 SourceLocation DefaultLoc,
8133 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls,
8134 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars)
8135 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8136 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8137 CollapsedLoopVarDecls(CollapsedLoopDecls),
8138 CollapsedLoopInductionVars(CollapsedLoopInductionVars) {}
8141 bool checkAndSetInit(Stmt *S,
bool EmitDiags =
true);
8144 bool checkAndSetCond(Expr *S);
8147 bool checkAndSetInc(Expr *S);
8149 ValueDecl *getLoopDecl()
const {
return LCDecl; }
8151 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
8153 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
8155 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
8157 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
8159 bool shouldSubtractStep()
const {
return SubtractStep; }
8161 bool isStrictTestOp()
const {
return TestIsStrictOp; }
8163 Expr *buildNumIterations(
8164 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces,
bool LimitedType,
8165 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8168 buildPreCond(Scope *S, Expr *
Cond,
8169 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8172 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8173 DSAStackTy &DSA)
const;
8176 Expr *buildPrivateCounterVar()
const;
8180 Expr *buildCounterStep()
const;
8184 buildOrderedLoopData(Scope *S, Expr *Counter,
8185 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8186 SourceLocation Loc, Expr *Inc =
nullptr,
8189 std::pair<Expr *, Expr *> buildMinMaxValues(
8190 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8192 Expr *buildFinalCondition(Scope *S)
const;
8194 bool dependent()
const;
8196 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
8198 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
8200 unsigned getLoopDependentIdx()
const {
8201 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8207 bool checkAndSetIncRHS(Expr *RHS);
8209 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8212 bool setUB(Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
8213 SourceRange SR, SourceLocation SL);
8215 bool setStep(Expr *NewStep,
bool Subtract);
8218bool OpenMPIterationSpaceChecker::dependent()
const {
8220 assert(!LB && !UB && !Step);
8228bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
8230 Expr *NewLB,
bool EmitDiags) {
8232 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
8233 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8237 LCRef = NewLCRefExpr;
8238 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8240 if ((Ctor->isCopyOrMoveConstructor() ||
8241 Ctor->isConvertingConstructor(
false)) &&
8242 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8246 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
8250bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
8254 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
8255 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8260 TestIsLessOp = LessOp;
8261 TestIsStrictOp = StrictOp;
8262 ConditionSrcRange = SR;
8264 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
8268bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
8270 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
8280 NewStep = Val.
get();
8293 std::optional<llvm::APSInt>
Result =
8304 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8305 if (UB && (IsConstZero ||
8306 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8307 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8309 diag::err_omp_loop_incr_not_compatible)
8311 SemaRef.
Diag(ConditionLoc,
8312 diag::note_omp_loop_cond_requires_compatible_incr)
8313 << *TestIsLessOp << ConditionSrcRange;
8316 if (*TestIsLessOp == Subtract) {
8320 Subtract = !Subtract;
8325 SubtractStep = Subtract;
8332class LoopCounterRefChecker final
8336 const ValueDecl *CurLCDecl =
nullptr;
8337 const ValueDecl *DepDecl =
nullptr;
8338 const ValueDecl *PrevDepDecl =
nullptr;
8339 bool IsInitializer =
true;
8340 bool SupportsNonRectangular;
8341 unsigned BaseLoopId = 0;
8342 bool checkDecl(
const Expr *E,
const ValueDecl *VD) {
8344 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8345 << (IsInitializer ? 0 : 1);
8348 const auto &&
Data = Stack.isLoopControlVariable(VD);
8353 SmallString<128> Name;
8354 llvm::raw_svector_ostream
OS(Name);
8358 diag::err_omp_wrong_dependency_iterator_type)
8360 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8363 if (
Data.first && !SupportsNonRectangular) {
8364 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_invariant_dependency);
8368 (DepDecl || (PrevDepDecl &&
8370 if (!DepDecl && PrevDepDecl)
8371 DepDecl = PrevDepDecl;
8372 SmallString<128> Name;
8373 llvm::raw_svector_ostream
OS(Name);
8377 diag::err_omp_invariant_or_linear_dependency)
8383 BaseLoopId =
Data.first;
8389 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
8390 const ValueDecl *VD = E->
getDecl();
8392 return checkDecl(E, VD);
8395 bool VisitMemberExpr(
const MemberExpr *E) {
8399 return checkDecl(E, VD);
8403 bool VisitStmt(
const Stmt *S) {
8405 for (
const Stmt *Child : S->
children())
8406 Res = (Child && Visit(Child)) || Res;
8409 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8410 const ValueDecl *CurLCDecl,
bool IsInitializer,
8411 const ValueDecl *PrevDepDecl =
nullptr,
8412 bool SupportsNonRectangular =
true)
8413 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8414 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8415 SupportsNonRectangular(SupportsNonRectangular) {}
8416 unsigned getBaseLoopId()
const {
8417 assert(CurLCDecl &&
"Expected loop dependency.");
8420 const ValueDecl *getDepDecl()
const {
8421 assert(CurLCDecl &&
"Expected loop dependency.");
8427std::optional<unsigned>
8428OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8429 bool IsInitializer) {
8431 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8432 DepDecl, SupportsNonRectangular);
8433 if (LoopStmtChecker.Visit(S)) {
8434 DepDecl = LoopStmtChecker.getDepDecl();
8435 return LoopStmtChecker.getBaseLoopId();
8437 return std::nullopt;
8440bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8451 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8455 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8456 if (!ExprTemp->cleanupsHaveSideEffects())
8457 S = ExprTemp->getSubExpr();
8459 if (!CollapsedLoopVarDecls.empty()) {
8460 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8461 if (!FSEC.TraverseStmt(S)) {
8463 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8464 <<
Range.getEnd() << 0 << FSEC.getForbiddenVar();
8474 SemaRef.Diag(Loc, diag::err_omp_loop_var_reused_in_collapsed_loop)
8482 if (
Expr *E = dyn_cast<Expr>(S))
8484 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8485 if (BO->getOpcode() == BO_Assign) {
8487 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8488 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8491 ValueDecl *LoopVar = ME->getMemberDecl();
8492 if (CheckLoopVarReuse(LoopVar, DRE->
getLocation()))
8494 return setLCDeclAndLB(LoopVar, ME, BO->getRHS(), EmitDiags);
8497 if (CheckLoopVarReuse(LoopVar, DRE->
getLocation()))
8499 return setLCDeclAndLB(LoopVar, DRE, BO->getRHS(), EmitDiags);
8501 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8502 if (ME->isArrow() &&
8504 ValueDecl *LoopVar = ME->getMemberDecl();
8505 if (CheckLoopVarReuse(LoopVar, LHS->
getBeginLoc()))
8507 return setLCDeclAndLB(LoopVar, ME, BO->getRHS(), EmitDiags);
8511 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8512 if (DS->isSingleDecl()) {
8513 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8514 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8518 diag::ext_omp_loop_not_canonical_init)
8520 if (CheckLoopVarReuse(Var, Var->getLocation()))
8522 return setLCDeclAndLB(
8525 Var->getType().getNonReferenceType(),
8527 Var->getInit(), EmitDiags);
8531 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8532 if (CE->getOperator() == OO_Equal) {
8533 Expr *LHS = CE->getArg(0);
8534 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8535 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8538 ValueDecl *LoopVar = ME->getMemberDecl();
8539 if (CheckLoopVarReuse(LoopVar, DRE->
getLocation()))
8541 return setLCDeclAndLB(LoopVar, ME, CE->getArg(1), EmitDiags);
8544 if (CheckLoopVarReuse(LoopVar, DRE->
getLocation()))
8546 return setLCDeclAndLB(LoopVar, DRE, CE->getArg(1), EmitDiags);
8548 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8549 if (ME->isArrow() &&
8551 ValueDecl *LoopVar = ME->getMemberDecl();
8552 if (CheckLoopVarReuse(LoopVar, LHS->
getBeginLoc()))
8554 return setLCDeclAndLB(LoopVar, ME, CE->getArg(1), EmitDiags);
8560 if (dependent() || SemaRef.CurContext->isDependentContext())
8563 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8575 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8577 if ((Ctor->isCopyOrMoveConstructor() ||
8578 Ctor->isConvertingConstructor(
false)) &&
8579 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8581 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8582 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8585 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8586 if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8591bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8598 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8600 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8601 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8607 if (!CollapsedLoopVarDecls.empty()) {
8608 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8609 if (!FSEC.TraverseStmt(S)) {
8611 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8612 <<
Range.getEnd() << 1 << FSEC.getForbiddenVar();
8618 auto &&CheckAndSetCond =
8623 if (getInitLCDecl(LHS) == LCDecl)
8624 return setUB(
const_cast<Expr *
>(RHS),
8625 (Opcode == BO_LT || Opcode == BO_LE),
8626 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8627 if (getInitLCDecl(RHS) == LCDecl)
8628 return setUB(
const_cast<Expr *
>(LHS),
8629 (Opcode == BO_GT || Opcode == BO_GE),
8630 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8631 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8632 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8636 return std::nullopt;
8638 std::optional<bool> Res;
8639 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8642 RBO->getOperatorLoc());
8643 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8644 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8645 BO->getSourceRange(), BO->getOperatorLoc());
8646 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8647 if (CE->getNumArgs() == 2) {
8648 Res = CheckAndSetCond(
8650 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8655 if (dependent() || SemaRef.CurContext->isDependentContext())
8657 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8658 << (IneqCondIsCanonical ? 1 : 0) << S->
getSourceRange() << LCDecl;
8662bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8669 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8670 if (BO->isAdditiveOp()) {
8671 bool IsAdd = BO->getOpcode() == BO_Add;
8672 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8673 return setStep(BO->getRHS(), !IsAdd);
8674 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8675 return setStep(BO->getLHS(),
false);
8677 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8678 bool IsAdd = CE->getOperator() == OO_Plus;
8679 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8680 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8681 return setStep(CE->getArg(1), !IsAdd);
8682 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8683 return setStep(CE->getArg(0),
false);
8686 if (dependent() || SemaRef.CurContext->isDependentContext())
8688 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8693bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8708 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8711 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8712 if (!ExprTemp->cleanupsHaveSideEffects())
8713 S = ExprTemp->getSubExpr();
8715 if (!CollapsedLoopVarDecls.empty()) {
8716 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8717 if (!FSEC.TraverseStmt(S)) {
8719 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8720 <<
Range.getEnd() << 2 << FSEC.getForbiddenVar();
8727 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8728 if (UO->isIncrementDecrementOp() &&
8729 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8730 return setStep(SemaRef
8731 .ActOnIntegerConstant(UO->getBeginLoc(),
8732 (UO->isDecrementOp() ? -1 : 1))
8735 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8736 switch (BO->getOpcode()) {
8739 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8740 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8743 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8744 return checkAndSetIncRHS(BO->getRHS());
8749 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8750 switch (CE->getOperator()) {
8753 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8754 return setStep(SemaRef
8755 .ActOnIntegerConstant(
8757 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8763 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8764 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8767 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8768 return checkAndSetIncRHS(CE->getArg(1));
8774 if (dependent() || SemaRef.CurContext->isDependentContext())
8776 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8783 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8784 StringRef Name =
".capture_expr.") {
8792 auto I = Captures.find(
Capture);
8793 if (I != Captures.end())
8806 bool TestIsStrictOp,
bool RoundToStep,
8807 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8808 std::optional<unsigned> InitDependOnLC,
8809 std::optional<unsigned> CondDependOnLC) {
8810 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8813 llvm::APSInt LRes, SRes;
8814 bool IsLowerConst =
false, IsStepConst =
false;
8815 if (std::optional<llvm::APSInt> Res =
8818 IsLowerConst =
true;
8820 if (std::optional<llvm::APSInt> Res =
8825 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8826 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8827 (TestIsStrictOp && LRes.isStrictlyPositive()));
8828 bool NeedToReorganize =
false;
8830 if (!NoNeedToConvert && IsLowerConst &&
8831 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8832 NoNeedToConvert =
true;
8834 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8835 ? LRes.getBitWidth()
8836 : SRes.getBitWidth();
8837 LRes = LRes.extend(BW + 1);
8838 LRes.setIsSigned(
true);
8839 SRes = SRes.extend(BW + 1);
8840 SRes.setIsSigned(
true);
8842 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8843 LRes = LRes.trunc(BW);
8845 if (TestIsStrictOp) {
8846 unsigned BW = LRes.getBitWidth();
8847 LRes = LRes.extend(BW + 1);
8848 LRes.setIsSigned(
true);
8851 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8853 LRes = LRes.trunc(BW);
8855 NeedToReorganize = NoNeedToConvert;
8858 bool IsUpperConst =
false;
8859 if (std::optional<llvm::APSInt> Res =
8862 IsUpperConst =
true;
8864 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8865 (!RoundToStep || IsStepConst)) {
8866 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8867 : URes.getBitWidth();
8868 LRes = LRes.extend(BW + 1);
8869 LRes.setIsSigned(
true);
8870 URes = URes.extend(BW + 1);
8871 URes.setIsSigned(
true);
8873 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8874 NeedToReorganize = NoNeedToConvert;
8879 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8885 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8888 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8899 if (!Lower || !Upper || NewStep.
isInvalid())
8908 if (TestIsStrictOp && InitDependOnLC.has_value() &&
8909 InitDependOnLC.value() >= 2 && !CondDependOnLC.has_value()) {
8910 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8925 if (NeedToReorganize) {
8939 S, DefaultLoc, BO_Add, Diff.
get(),
8949 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8953 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8969 S, DefaultLoc, BO_Sub, Diff.
get(),
8989 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8997Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8999 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9008 if (InitDependOnLC) {
9009 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
9010 if (!IS.MinValue || !IS.MaxValue)
9019 IS.CounterVar, MinValue.
get());
9024 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
9039 IS.CounterVar, MaxValue.
get());
9044 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
9053 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
9055 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
9056 if (!LBMin || !LBMax)
9060 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
9064 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
9068 if (*TestIsLessOp) {
9072 MinLessMax, LBMin, LBMax);
9075 LBVal = MinLB.
get();
9080 MinLessMax, LBMax, LBMin);
9083 LBVal = MaxLB.
get();
9087 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
9090 LBVal = LBMinVal.
get();
9094 if (CondDependOnLC) {
9095 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9096 if (!IS.MinValue || !IS.MaxValue)
9105 IS.CounterVar, MinValue.
get());
9110 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
9125 IS.CounterVar, MaxValue.
get());
9130 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
9139 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
9141 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
9142 if (!UBMin || !UBMax)
9146 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9149 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
9150 Captures,
".min_greater_max")
9154 if (*TestIsLessOp) {
9158 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9161 UBVal = MaxUB.
get();
9166 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9169 UBVal = MinUB.
get();
9172 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9173 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9174 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
9175 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
9176 if (!Upper || !Lower)
9180 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9181 true, Captures, InitDependOnLC, CondDependOnLC);
9189 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
9192 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
9195 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
9205 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
9206 if (NewSize !=
C.getTypeSize(
Type)) {
9207 if (NewSize <
C.getTypeSize(
Type)) {
9208 assert(NewSize == 64 &&
"incorrect loop var size");
9209 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9210 << InitSrcRange << ConditionSrcRange;
9212 QualType NewType =
C.getIntTypeForBitwidth(
9214 C.getTypeSize(
Type) < NewSize);
9228std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9229 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9233 return std::make_pair(
nullptr,
nullptr);
9236 Expr *MinExpr =
nullptr;
9237 Expr *MaxExpr =
nullptr;
9238 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9239 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9241 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9243 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9245 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9247 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9248 if (!Upper || !Lower)
9249 return std::make_pair(
nullptr,
nullptr);
9260 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9261 false, Captures, InitDependOnLC, CondDependOnLC);
9264 return std::make_pair(
nullptr,
nullptr);
9270 return std::make_pair(
nullptr,
nullptr);
9272 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
9274 return std::make_pair(
nullptr,
nullptr);
9275 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
9277 return std::make_pair(
nullptr,
nullptr);
9282 return std::make_pair(
nullptr,
nullptr);
9294 return std::make_pair(
nullptr,
nullptr);
9296 if (*TestIsLessOp) {
9300 S, DefaultLoc, BO_Add,
9304 return std::make_pair(
nullptr,
nullptr);
9309 S, DefaultLoc, BO_Sub,
9313 return std::make_pair(
nullptr,
nullptr);
9322 return std::make_pair(
nullptr,
nullptr);
9327 return std::make_pair(
nullptr,
nullptr);
9330 MaxExpr = Diff.
get();
9332 MinExpr = Diff.
get();
9334 return std::make_pair(MinExpr, MaxExpr);
9337Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
9338 if (InitDependOnLC || CondDependOnLC)
9343Expr *OpenMPIterationSpaceChecker::buildPreCond(
9345 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9350 if (CondDependOnLC || InitDependOnLC)
9361 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9362 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9368 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9369 : (TestIsStrictOp ? BO_GT : BO_GE),
9370 NewLB.
get(), NewUB.
get());
9385DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9386 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9387 DSAStackTy &DSA)
const {
9388 auto *VD = dyn_cast<VarDecl>(LCDecl);
9393 const DSAStackTy::DSAVarData
Data =
9394 DSA.getTopDSA(LCDecl,
false);
9398 Captures.insert(std::make_pair(LCRef, Ref));
9404Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9421Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9424Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9426Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9428 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
SourceLocation Loc,
9434 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9435 "Expected only + or - operations for depend clauses.");
9447 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9449 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9450 if (!Upper || !Lower)
9454 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9456 Captures, InitDependOnLC, CondDependOnLC);
9466 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9467 assert(
Init &&
"Expected loop in canonical form.");
9468 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9475 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9478 if (!ISC.checkAndSetInit(
Init,
false)) {
9480 auto *VD = dyn_cast<VarDecl>(D);
9491 DSAStack->addLoopControlVariable(D, VD);
9493 if (LD != D->getCanonicalDecl()) {
9494 DSAStack->resetPossibleLoopCounter();
9495 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9508 DSAStackTy::DSAVarData DVar =
9512 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9515 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9518 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9521 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9523 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9525 IsOpenMPTaskloopDirective(DKind) ||
9528 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9529 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9531 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9533 << getOpenMPDirectiveName(DKind, OMPVersion)
9535 if (DVar.RefExpr ==
nullptr)
9536 DVar.CKind = PredeterminedCKind;
9538 }
else if (LoopDeclRefExpr) {
9543 if (DVar.CKind == OMPC_unknown)
9544 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9548 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9553class OMPDoacrossKind {
9556 return C->getDependenceType() == OMPC_DOACROSS_source ||
9557 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9560 return C->getDependenceType() == OMPC_DOACROSS_sink;
9562 bool isSinkIter(
const OMPDoacrossClause *
C) {
9563 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9571 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9572 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9573 Expr *OrderedLoopCountExpr,
9576 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9577 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls,
9578 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars) {
9583 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9584 S = CanonLoop->getLoopStmt();
9585 auto *For = dyn_cast_or_null<ForStmt>(S);
9586 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9588 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9589 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
9591 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9592 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9593 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9594 if (TotalNestedLoopCount > 1) {
9595 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9596 SemaRef.
Diag(DSA.getConstructLoc(),
9597 diag::note_omp_collapse_ordered_expr)
9600 else if (CollapseLoopCountExpr)
9602 diag::note_omp_collapse_ordered_expr)
9604 else if (OrderedLoopCountExpr)
9606 diag::note_omp_collapse_ordered_expr)
9611 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9617 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9618 For ? For->getForLoc() : CXXFor->getForLoc(),
9619 CollapsedLoopVarDecls,
9620 CollapsedLoopInductionVars);
9623 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9624 if (ISC.checkAndSetInit(
Init))
9627 bool HasErrors =
false;
9630 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9640 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9654 VarsWithImplicitDSA.erase(LCDecl);
9658 "DSA for non-loop vars");
9661 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9664 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9671 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9672 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9673 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9674 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9681 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9682 ISC.buildCounterVar(Captures, DSA);
9683 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9684 ISC.buildPrivateCounterVar();
9685 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9686 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9687 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9688 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9689 ISC.getConditionSrcRange();
9690 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9691 ISC.getIncrementSrcRange();
9692 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9693 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9694 ISC.isStrictTestOp();
9695 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9696 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9697 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9698 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9699 ISC.buildFinalCondition(DSA.getCurScope());
9700 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9701 ISC.doesInitDependOnLC();
9702 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9703 ISC.doesCondDependOnLC();
9704 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9705 ISC.getLoopDependentIdx();
9708 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9709 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9710 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9711 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9712 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9713 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9714 if (!HasErrors && DSA.isOrderedRegion()) {
9715 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9716 if (CurrentNestedLoopCount <
9717 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9718 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9719 CurrentNestedLoopCount,
9720 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9721 DSA.getOrderedRegionParam().second->setLoopCounter(
9722 CurrentNestedLoopCount,
9723 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9726 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9727 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9728 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9730 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9731 if (CurrentNestedLoopCount >= NumLoops) {
9735 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9736 Pair.second.size() <= CurrentNestedLoopCount) {
9738 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9741 OMPDoacrossKind ODK;
9742 if (DoacrossC && ODK.isSink(DoacrossC) &&
9743 Pair.second.size() <= CurrentNestedLoopCount) {
9745 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9750 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9751 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9752 (DoacrossC && ODK.isSource(DoacrossC)))
9753 CntValue = ISC.buildOrderedLoopData(
9755 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9757 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9760 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9768 CntValue = ISC.buildOrderedLoopData(
9770 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9771 DepLoc, Inc, clang::OO_Minus);
9773 CntValue = ISC.buildOrderedLoopData(
9775 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9776 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9777 Pair.second[CurrentNestedLoopCount].second);
9779 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9781 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9785 if (CurrentNestedLoopCount < NestedLoopCount && !HasErrors) {
9786 if (
const ValueDecl *LCDecl = ISC.getLoopDecl())
9796 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9800 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9821 bool IsNonRectangularLB,
9822 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9831 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9846 if (Captures && !IsNonRectangularLB)
9847 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9856 Update.get()->getType()->isOverloadableType()) {
9863 SemaRef.
BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9864 VarRef.
get(), SavedUpdate.
get());
9875 NewStart.
get(), SavedUpdate.
get());
9900 unsigned HasBits =
C.getTypeSize(OldType);
9901 if (HasBits >= Bits)
9904 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9914 if (std::optional<llvm::APSInt>
Result =
9923 if (!PreInits.empty()) {
9944 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9953 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9954 if (!Captures.empty()) {
9956 for (
const auto &Pair : Captures)
9957 PreInits.push_back(Pair.second->getDecl());
9965 if (PreInits.empty())
9969 for (
Stmt *S : PreInits)
9976 Expr *PostUpdate =
nullptr;
9977 if (!PostUpdates.empty()) {
9978 for (
Expr *E : PostUpdates) {
9984 PostUpdate = PostUpdate
9998 int NestingDepth = 0;
9999 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
10021 if (NestingDepth > 0)
10022 VarDecls.insert(
C);
10032 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
10035 OMPLoopBasedDirective::HelperExprs &Built) {
10039 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->
containsErrors()) ||
10040 (OrderedLoopCountExpr && OrderedLoopCountExpr->
containsErrors()))
10043 unsigned NestedLoopCount = 1;
10044 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
10049 if (CollapseLoopCountExpr) {
10054 NestedLoopCount =
Result.Val.getInt().getLimitedValue();
10063 unsigned OrderedLoopCount = 1;
10064 if (OrderedLoopCountExpr) {
10071 if (
Result.getLimitedValue() < NestedLoopCount) {
10073 diag::err_omp_wrong_ordered_loop_count)
10076 diag::note_collapse_loop_count)
10079 OrderedLoopCount =
Result.getLimitedValue();
10087 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
10088 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
10090 if (!OMPLoopBasedDirective::doForAllLoops(
10093 SupportsNonPerfectlyNested, NumLoops,
10094 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10095 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10096 &IterSpaces, &Captures, &CollapsedLoopVarDecls,
10097 &CollapsedLoopInductionVars](
unsigned Cnt,
Stmt *CurStmt) {
10099 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
10100 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10101 VarsWithImplicitDSA, IterSpaces, Captures,
10102 CollapsedLoopVarDecls, CollapsedLoopInductionVars))
10104 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10105 IterSpaces[Cnt].CounterVar) {
10109 Captures[DRE] = DRE;
10115 Stmt *DependentPreInits = Transform->getPreInits();
10116 if (!DependentPreInits)
10123 for (
Stmt *S : Constituents) {
10124 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
10125 for (
Decl *
C : DC->decls()) {
10128 SemaRef, D, D->getType().getNonReferenceType(),
10131 Captures[Ref] = Ref;
10138 Built.clear(NestedLoopCount);
10141 return NestedLoopCount;
10174 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
10175 Expr *N0 = IterSpaces[0].NumIterations;
10194 return NestedLoopCount;
10197 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
10199 Scope *CurScope = DSA.getCurScope();
10200 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10201 if (PreCond.isUsable()) {
10203 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10204 PreCond.get(), IterSpaces[Cnt].PreCond);
10206 Expr *N = IterSpaces[Cnt].NumIterations;
10208 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
10211 CurScope, Loc, BO_Mul, LastIteration32.
get(),
10219 CurScope, Loc, BO_Mul, LastIteration64.
get(),
10229 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
10231 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
10232 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10236 LastIteration64.
get(), SemaRef))))
10237 LastIteration = LastIteration32;
10256 LastIteration.
get(),
10268 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
10269 LastIteration = SaveRef;
10282 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10311 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
10320 UB.
get(), LastIteration.
get());
10323 LastIteration.
get(), UB.
get());
10324 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
10335 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.lb");
10343 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.ub");
10349 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
10352 LastIteration.
get(), CombUB.
get());
10353 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
10362 "Unexpected number of parameters in loop combined directive");
10403 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
10409 bool UseStrictCompare =
10411 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
10412 return LIS.IsStrictCompare;
10418 if (UseStrictCompare) {
10421 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10433 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10436 NumIterations.
get());
10439 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10440 NumIterations.
get());
10445 Expr *BoundCombUB = CombUB.
get();
10446 if (UseStrictCompare) {
10450 CurScope, CondLoc, BO_Add, BoundCombUB,
10458 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10459 IV.
get(), BoundCombUB);
10466 if (!Inc.isUsable())
10468 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10470 if (!Inc.isUsable())
10477 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10483 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10494 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10510 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10522 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10536 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10539 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10540 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10544 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10545 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10549 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10560 DistEUBLoc, NewPrevUB.
get());
10565 UB.
get(), NewPrevUB.
get());
10567 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10568 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10576 Expr *BoundPrevUB = PrevUB.
get();
10577 if (UseStrictCompare) {
10581 CurScope, CondLoc, BO_Add, BoundPrevUB,
10589 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10590 IV.
get(), BoundPrevUB);
10594 bool HasErrors =
false;
10595 Built.Counters.resize(NestedLoopCount);
10596 Built.Inits.resize(NestedLoopCount);
10597 Built.Updates.resize(NestedLoopCount);
10598 Built.Finals.resize(NestedLoopCount);
10599 Built.DependentCounters.resize(NestedLoopCount);
10600 Built.DependentInits.resize(NestedLoopCount);
10601 Built.FinalsConditions.resize(NestedLoopCount);
10619 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10620 LoopIterationSpace &IS = IterSpaces[Cnt];
10626 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10627 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10628 IterSpaces[K].NumIterations);
10633 if (Cnt + 1 < NestedLoopCount)
10647 if (Cnt + 1 < NestedLoopCount)
10648 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.
get(),
10652 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10661 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10662 if (!
Init.isUsable()) {
10667 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10668 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10669 if (!
Update.isUsable()) {
10677 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10678 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10679 if (!Final.isUsable()) {
10684 if (!
Update.isUsable() || !Final.isUsable()) {
10689 Built.Counters[Cnt] = IS.CounterVar;
10690 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10691 Built.Inits[Cnt] =
Init.get();
10692 Built.Updates[Cnt] =
Update.get();
10693 Built.Finals[Cnt] = Final.get();
10694 Built.DependentCounters[Cnt] =
nullptr;
10695 Built.DependentInits[Cnt] =
nullptr;
10696 Built.FinalsConditions[Cnt] =
nullptr;
10697 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10698 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10699 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10700 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10709 Built.IterationVarRef = IV.
get();
10710 Built.LastIteration = LastIteration.
get();
10711 Built.NumIterations = NumIterations.
get();
10712 Built.CalcLastIteration = SemaRef
10716 Built.PreCond = PreCond.get();
10718 Built.Cond =
Cond.get();
10719 Built.Init =
Init.get();
10720 Built.Inc = Inc.get();
10721 Built.LB = LB.
get();
10722 Built.UB = UB.
get();
10723 Built.IL = IL.
get();
10724 Built.ST = ST.
get();
10725 Built.EUB = EUB.
get();
10726 Built.NLB = NextLB.
get();
10727 Built.NUB = NextUB.
get();
10728 Built.PrevLB = PrevLB.
get();
10729 Built.PrevUB = PrevUB.
get();
10730 Built.DistInc = DistInc.
get();
10731 Built.PrevEUB = PrevEUB.
get();
10732 Built.DistCombinedFields.LB = CombLB.
get();
10733 Built.DistCombinedFields.UB = CombUB.
get();
10734 Built.DistCombinedFields.EUB = CombEUB.
get();
10735 Built.DistCombinedFields.Init = CombInit.
get();
10736 Built.DistCombinedFields.Cond = CombCond.
get();
10737 Built.DistCombinedFields.NLB = CombNextLB.
get();
10738 Built.DistCombinedFields.NUB = CombNextUB.
get();
10739 Built.DistCombinedFields.DistCond = CombDistCond.
get();
10740 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.
get();
10742 return NestedLoopCount;
10746 auto CollapseClauses =
10747 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10748 if (CollapseClauses.begin() != CollapseClauses.end())
10749 return (*CollapseClauses.begin())->getNumForLoops();
10754 auto OrderedClauses =
10755 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10756 if (OrderedClauses.begin() != OrderedClauses.end())
10757 return (*OrderedClauses.begin())->getNumForLoops();
10766 for (
const OMPClause *Clause : Clauses) {
10767 if (Clause->getClauseKind() == OMPC_safelen)
10769 else if (Clause->getClauseKind() == OMPC_simdlen)
10771 if (Safelen && Simdlen)
10775 if (Simdlen && Safelen) {
10789 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10790 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10795 if (SimdlenRes > SafelenRes) {
10797 diag::err_omp_wrong_simdlen_safelen_values)
10814 OMPLoopBasedDirective::HelperExprs B;
10820 if (NestedLoopCount == 0)
10829 auto *SimdDirective = OMPSimdDirective::Create(
10830 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10831 return SimdDirective;
10841 OMPLoopBasedDirective::HelperExprs B;
10847 if (NestedLoopCount == 0)
10853 auto *ForDirective = OMPForDirective::Create(
10854 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10856 return ForDirective;
10868 OMPLoopBasedDirective::HelperExprs B;
10871 unsigned NestedLoopCount =
10874 VarsWithImplicitDSA, B);
10875 if (NestedLoopCount == 0)
10884 return OMPForSimdDirective::Create(
getASTContext(), StartLoc, EndLoc,
10885 NestedLoopCount, Clauses, AStmt, B);
10889 Stmt *AStmt, DSAStackTy *Stack) {
10894 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
10895 auto BaseStmt = AStmt;
10896 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10898 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10899 auto S =
C->children();
10900 if (S.begin() == S.end())
10904 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10907 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10908 diag::err_omp_sections_substmt_not_section)
10909 << getOpenMPDirectiveName(DKind, OMPVersion);
10913 ->setHasCancel(Stack->isCancelRegion());
10916 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10917 << getOpenMPDirectiveName(DKind, OMPVersion);
10930 SemaRef.setFunctionHasBranchProtectedScope();
10932 return OMPSectionsDirective::Create(
10943 SemaRef.setFunctionHasBranchProtectedScope();
10946 return OMPSectionDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt,
10952 if (
auto *CE = dyn_cast<CallExpr>(E))
10953 if (CE->getDirectCallee())
10974 if (!
SemaRef.CurContext->isDependentContext()) {
10975 Expr *TargetCall =
nullptr;
10977 auto *E = dyn_cast<Expr>(S);
10985 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
10986 if (BO->getOpcode() == BO_Assign)
10989 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10990 if (COCE->getOperator() == OO_Equal)
11002 SemaRef.setFunctionHasBranchProtectedScope();
11005 Clauses, AStmt, TargetCallLoc);
11010 DSAStackTy *Stack) {
11011 bool ErrorFound =
false;
11013 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
11014 for (
Expr *RefExpr : LPC->varlist()) {
11017 Expr *SimpleRefExpr = RefExpr;
11020 auto &&Info = Stack->isLoopControlVariable(D);
11023 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
11024 << getOpenMPDirectiveName(K, OMPVersion);
11048 OMPLoopDirective::HelperExprs B;
11053 if (NestedLoopCount == 0)
11056 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11057 "omp loop exprs were not built");
11060 NestedLoopCount, Clauses, AStmt, B);
11077 OMPLoopDirective::HelperExprs B;
11079 unsigned NestedLoopCount =
11082 VarsWithImplicitDSA, B);
11083 if (NestedLoopCount == 0)
11086 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11087 "omp loop exprs were not built");
11089 DSAStack->setParentTeamsRegionLoc(StartLoc);
11092 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11111 OMPLoopDirective::HelperExprs B;
11113 unsigned NestedLoopCount =
11116 VarsWithImplicitDSA, B);
11117 if (NestedLoopCount == 0)
11120 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11121 "omp loop exprs were not built");
11124 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11144 OMPLoopDirective::HelperExprs B;
11146 unsigned NestedLoopCount =
11149 VarsWithImplicitDSA, B);
11150 if (NestedLoopCount == 0)
11153 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11154 "omp loop exprs were not built");
11157 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11176 OMPLoopDirective::HelperExprs B;
11178 unsigned NestedLoopCount =
11181 VarsWithImplicitDSA, B);
11182 if (NestedLoopCount == 0)
11185 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11186 "omp loop exprs were not built");
11189 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11201 SemaRef.setFunctionHasBranchProtectedScope();
11206 const OMPClause *Copyprivate =
nullptr;
11207 for (
const OMPClause *Clause : Clauses) {
11208 if (Clause->getClauseKind() == OMPC_nowait)
11210 else if (Clause->getClauseKind() == OMPC_copyprivate)
11211 Copyprivate = Clause;
11212 if (Copyprivate && Nowait) {
11214 diag::err_omp_single_copyprivate_with_nowait);
11220 return OMPSingleDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11230 SemaRef.setFunctionHasBranchProtectedScope();
11232 return OMPMasterDirective::Create(
getASTContext(), StartLoc, EndLoc, AStmt);
11242 SemaRef.setFunctionHasBranchProtectedScope();
11254 bool ErrorFound =
false;
11257 bool DependentHint =
false;
11259 if (
C->getClauseKind() == OMPC_hint) {
11261 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11267 DependentHint =
true;
11270 HintLoc =
C->getBeginLoc();
11276 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
11277 if (Pair.first && DirName.
getName() && !DependentHint) {
11278 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11279 Diag(StartLoc, diag::err_omp_critical_with_hint);
11281 Diag(HintLoc, diag::note_omp_critical_hint_here)
11282 << 0 <<
toString(Hint, 10,
false);
11284 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11285 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
11286 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
11291 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11296 SemaRef.setFunctionHasBranchProtectedScope();
11298 auto *Dir = OMPCriticalDirective::Create(
getASTContext(), DirName, StartLoc,
11299 EndLoc, Clauses, AStmt);
11300 if (!Pair.first && DirName.
getName() && !DependentHint)
11301 DSAStack->addCriticalWithHint(Dir, Hint);
11313 OMPLoopBasedDirective::HelperExprs B;
11316 unsigned NestedLoopCount =
11319 VarsWithImplicitDSA, B);
11320 if (NestedLoopCount == 0)
11326 return OMPParallelForDirective::Create(
11327 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11340 OMPLoopBasedDirective::HelperExprs B;
11343 unsigned NestedLoopCount =
11346 VarsWithImplicitDSA, B);
11347 if (NestedLoopCount == 0)
11356 return OMPParallelForSimdDirective::Create(
11357 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11368 return OMPParallelMasterDirective::Create(
11370 DSAStack->getTaskgroupReductionRef());
11381 return OMPParallelMaskedDirective::Create(
11383 DSAStack->getTaskgroupReductionRef());
11392 SemaRef.setFunctionHasBranchProtectedScope();
11394 return OMPParallelSectionsDirective::Create(
11404 bool ErrorFound =
false;
11406 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
11410 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11433 {OMPC_detach, OMPC_mergeable}))
11438 return OMPTaskDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11439 AStmt,
DSAStack->isCancelRegion());
11444 return OMPTaskyieldDirective::Create(
getASTContext(), StartLoc, EndLoc);
11449 return OMPBarrierDirective::Create(
getASTContext(), StartLoc, EndLoc);
11455 bool InExContext) {
11456 const OMPAtClause *AtC =
11457 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11459 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11460 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11464 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11465 const OMPSeverityClause *SeverityC =
11466 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11467 const OMPMessageClause *MessageC =
11468 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11469 std::optional<std::string> SL =
11470 MessageC ? MessageC->tryEvaluateString(
getASTContext()) : std::nullopt;
11472 if (MessageC && !SL)
11473 Diag(MessageC->getMessageString()->getBeginLoc(),
11474 diag::warn_clause_expected_string)
11476 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11477 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11478 << SL.value_or(
"WARNING");
11480 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or(
"ERROR");
11481 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11492 const OMPNowaitClause *NowaitC =
11493 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11495 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11497 if (NowaitC && !HasDependC) {
11498 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11502 return OMPTaskwaitDirective::Create(
getASTContext(), StartLoc, EndLoc,
11515 SemaRef.setFunctionHasBranchProtectedScope();
11517 return OMPTaskgroupDirective::Create(
getASTContext(), StartLoc, EndLoc,
11519 DSAStack->getTaskgroupReductionRef());
11528 if (
C->getClauseKind() == OMPC_flush)
11537 if (
C->getClauseKind() == OMPC_acq_rel ||
11538 C->getClauseKind() == OMPC_acquire ||
11539 C->getClauseKind() == OMPC_release ||
11540 C->getClauseKind() == OMPC_seq_cst ) {
11541 if (MemOrderKind != OMPC_unknown) {
11542 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11543 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11545 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11548 MemOrderKind =
C->getClauseKind();
11549 MemOrderLoc =
C->getBeginLoc();
11553 if (FC && OrderClause) {
11554 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11556 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11560 return OMPFlushDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11566 if (Clauses.empty()) {
11567 Diag(StartLoc, diag::err_omp_depobj_expected);
11569 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11570 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11574 if (Clauses.size() > 2) {
11575 Diag(Clauses[2]->getBeginLoc(),
11576 diag::err_omp_depobj_single_clause_expected);
11578 }
else if (Clauses.size() < 1) {
11579 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11582 return OMPDepobjDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses);
11589 if (Clauses.size() != 1) {
11590 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11591 diag::err_omp_scan_single_clause_expected);
11600 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11601 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11606 if (
DSAStack->doesParentHasScanDirective()) {
11607 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11609 diag::note_omp_previous_directive)
11613 DSAStack->setParentHasScanDirective(StartLoc);
11621 const OMPClause *DependFound =
nullptr;
11622 const OMPClause *DependSourceClause =
nullptr;
11623 const OMPClause *DependSinkClause =
nullptr;
11624 const OMPClause *DoacrossFound =
nullptr;
11625 const OMPClause *DoacrossSourceClause =
nullptr;
11626 const OMPClause *DoacrossSinkClause =
nullptr;
11627 bool ErrorFound =
false;
11631 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11632 auto DC = dyn_cast<OMPDependClause>(
C);
11634 DependFound = DC ?
C :
nullptr;
11635 DoacrossFound = DOC ?
C :
nullptr;
11636 OMPDoacrossKind ODK;
11637 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11638 (DOC && (ODK.isSource(DOC)))) {
11639 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11641 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11642 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11648 DependSourceClause =
C;
11650 DoacrossSourceClause =
C;
11652 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11653 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11654 << (DC ?
"depend" :
"doacross") << 0;
11657 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11658 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11659 if (DependSourceClause || DoacrossSourceClause) {
11660 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11661 << (DC ?
"depend" :
"doacross") << 1;
11665 DependSinkClause =
C;
11667 DoacrossSinkClause =
C;
11669 }
else if (
C->getClauseKind() == OMPC_threads) {
11671 }
else if (
C->getClauseKind() == OMPC_simd) {
11675 if (!ErrorFound && !SC &&
11680 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11683 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11686 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11689 : SC->getClauseKind());
11691 }
else if ((DependFound || DoacrossFound) &&
11692 !
DSAStack->getParentOrderedRegionParam().first) {
11695 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11699 }
else if (TC || Clauses.empty()) {
11700 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11702 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11703 << (TC !=
nullptr);
11704 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11708 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11716 if (!DependFound && !DoacrossFound) {
11717 if (
DSAStack->doesParentHasOrderedDirective()) {
11718 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11720 diag::note_omp_previous_directive)
11724 DSAStack->setParentHasOrderedDirective(StartLoc);
11730 SemaRef.setFunctionHasBranchProtectedScope();
11733 return OMPOrderedDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
11740class OpenMPAtomicUpdateChecker {
11742 enum ExprAnalysisErrorCode {
11746 NotABinaryOrUnaryExpression,
11748 NotAnUnaryIncDecExpression,
11754 NotABinaryExpression,
11757 NotABinaryOperator,
11760 NotAnUpdateExpression,
11763 NotAValidExpression,
11789 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11799 bool checkStatement(Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11801 Expr *
getX()
const {
return X; }
11803 Expr *
getExpr()
const {
return E; }
11817 bool checkBinaryOperation(BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11818 unsigned NoteId = 0);
11821bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11822 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11823 ExprAnalysisErrorCode ErrorFound = NoError;
11829 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11831 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11833 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11834 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11835 AtomicInnerBinOp->isBitwiseOp()) {
11836 Op = AtomicInnerBinOp->getOpcode();
11837 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11838 Expr *LHS = AtomicInnerBinOp->getLHS();
11839 Expr *RHS = AtomicInnerBinOp->getRHS();
11840 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11847 if (XId == LHSId) {
11850 }
else if (XId == RHSId) {
11854 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11855 ErrorRange = AtomicInnerBinOp->getSourceRange();
11856 NoteLoc =
X->getExprLoc();
11857 NoteRange =
X->getSourceRange();
11858 ErrorFound = NotAnUpdateExpression;
11861 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11862 ErrorRange = AtomicInnerBinOp->getSourceRange();
11863 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11865 ErrorFound = NotABinaryOperator;
11870 ErrorFound = NotABinaryExpression;
11877 ErrorFound = NotAnAssignmentOp;
11879 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11880 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11881 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11885 E =
X = UpdateExpr =
nullptr;
11886 return ErrorFound != NoError;
11889bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11891 ExprAnalysisErrorCode ErrorFound = NoError;
11902 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11903 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11904 if (AtomicBody->getType()->isScalarType() ||
11905 AtomicBody->isInstantiationDependent()) {
11906 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11907 AtomicBody->IgnoreParenImpCasts())) {
11910 AtomicCompAssignOp->getOpcode());
11911 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11912 E = AtomicCompAssignOp->getRHS();
11915 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11916 AtomicBody->IgnoreParenImpCasts())) {
11918 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11920 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11921 AtomicBody->IgnoreParenImpCasts())) {
11923 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11925 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11926 OpLoc = AtomicUnaryOp->getOperatorLoc();
11927 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11931 ErrorFound = NotAnUnaryIncDecExpression;
11932 ErrorLoc = AtomicUnaryOp->getExprLoc();
11933 ErrorRange = AtomicUnaryOp->getSourceRange();
11934 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11937 }
else if (!AtomicBody->isInstantiationDependent()) {
11938 ErrorFound = NotABinaryOrUnaryExpression;
11939 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11940 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11941 }
else if (AtomicBody->containsErrors()) {
11942 ErrorFound = NotAValidExpression;
11943 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11944 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11947 ErrorFound = NotAScalarType;
11948 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11949 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11952 ErrorFound = NotAnExpression;
11954 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11956 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11957 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11958 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11962 E =
X = UpdateExpr =
nullptr;
11963 if (ErrorFound == NoError && E &&
X) {
11980 UpdateExpr =
Update.get();
11982 return ErrorFound != NoError;
11986llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11987 llvm::FoldingSetNodeID Id;
11993bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11995 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11998class OpenMPAtomicCompareChecker {
12045 struct ErrorInfoTy {
12047 SourceLocation ErrorLoc;
12048 SourceRange ErrorRange;
12049 SourceLocation NoteLoc;
12050 SourceRange NoteRange;
12053 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
12056 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12058 Expr *
getX()
const {
return X; }
12059 Expr *getE()
const {
return E; }
12060 Expr *
getD()
const {
return D; }
12061 Expr *getCond()
const {
return C; }
12062 bool isXBinopExpr()
const {
return IsXBinopExpr; }
12066 ASTContext &ContextRef;
12081 bool IsXBinopExpr =
true;
12084 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
12087 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12090 bool checkType(ErrorInfoTy &ErrorInfo)
const;
12092 static bool CheckValue(
const Expr *E, ErrorInfoTy &ErrorInfo,
12093 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
12097 if (ShouldBeLValue && !E->
isLValue()) {
12098 ErrorInfo.Error = ErrorTy::XNotLValue;
12099 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
12100 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
12106 ErrorInfo.Error = ErrorTy::NotScalar;
12107 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
12108 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
12112 ErrorInfo.Error = ErrorTy::NotInteger;
12113 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
12114 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
12122bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
12123 ErrorInfoTy &ErrorInfo) {
12125 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12126 if (CS->body_empty()) {
12127 ErrorInfo.Error = ErrorTy::NoStmt;
12128 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12129 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12132 if (CS->size() > 1) {
12133 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12134 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12135 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12138 Then = CS->body_front();
12141 auto *BO = dyn_cast<BinaryOperator>(Then);
12143 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12144 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12145 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12148 if (BO->getOpcode() != BO_Assign) {
12149 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12150 ErrorInfo.ErrorLoc = BO->getExprLoc();
12151 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12152 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12158 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12159 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12160 Expr *LHS =
nullptr;
12161 Expr *RHS =
nullptr;
12163 LHS =
Cond->getLHS();
12164 RHS =
Cond->getRHS();
12166 LHS =
Call->getArg(0);
12167 RHS =
Call->getArg(1);
12169 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12175 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12176 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12179 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12181 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12184 ErrorInfo.Error = ErrorTy::InvalidComparison;
12186 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12190 }
else if ((
Cond &&
12191 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12193 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12194 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12196 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12197 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12199 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12200 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12202 IsXBinopExpr =
false;
12204 ErrorInfo.Error = ErrorTy::InvalidComparison;
12206 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12211 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12218 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12227bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
12228 ErrorInfoTy &ErrorInfo) {
12229 auto *BO = dyn_cast<BinaryOperator>(S);
12231 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12232 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12233 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12236 if (BO->getOpcode() != BO_Assign) {
12237 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12238 ErrorInfo.ErrorLoc = BO->getExprLoc();
12239 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12240 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12246 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12248 ErrorInfo.Error = ErrorTy::NotCondOp;
12249 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12250 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12254 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
12255 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12256 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12257 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12258 CO->getFalseExpr()->getSourceRange();
12262 auto *
Cond = dyn_cast<BinaryOperator>(CO->getCond());
12263 auto *
Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12264 Expr *LHS =
nullptr;
12265 Expr *RHS =
nullptr;
12267 LHS =
Cond->getLHS();
12268 RHS =
Cond->getRHS();
12270 LHS =
Call->getArg(0);
12271 RHS =
Call->getArg(1);
12273 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12274 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12275 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12276 CO->getCond()->getSourceRange();
12280 if ((
Cond &&
Cond->getOpcode() == BO_EQ) ||
12281 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12283 D = CO->getTrueExpr();
12284 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12286 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12289 ErrorInfo.Error = ErrorTy::InvalidComparison;
12290 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12291 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12292 CO->getCond()->getSourceRange();
12295 }
else if ((
Cond &&
12296 (
Cond->getOpcode() == BO_LT ||
Cond->getOpcode() == BO_GT)) ||
12298 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12299 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12301 E = CO->getTrueExpr();
12302 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
12303 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12305 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12306 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12308 IsXBinopExpr =
false;
12310 ErrorInfo.Error = ErrorTy::InvalidComparison;
12311 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12312 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12313 CO->getCond()->getSourceRange();
12317 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12318 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12319 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12320 CO->getCond()->getSourceRange();
12327bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
12329 assert(
X && E &&
"X and E cannot be nullptr");
12331 if (!CheckValue(
X, ErrorInfo,
true))
12334 if (!CheckValue(E, ErrorInfo,
false))
12337 if (D && !CheckValue(D, ErrorInfo,
false))
12343bool OpenMPAtomicCompareChecker::checkStmt(
12344 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12345 auto *CS = dyn_cast<CompoundStmt>(S);
12347 if (CS->body_empty()) {
12348 ErrorInfo.Error = ErrorTy::NoStmt;
12349 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12350 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12354 if (CS->size() != 1) {
12355 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12356 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12357 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12360 S = CS->body_front();
12365 if (
auto *IS = dyn_cast<IfStmt>(S)) {
12371 Res = checkCondUpdateStmt(IS, ErrorInfo);
12377 Res = checkCondExprStmt(S, ErrorInfo);
12383 return checkType(ErrorInfo);
12386class OpenMPAtomicCompareCaptureChecker final
12387 :
public OpenMPAtomicCompareChecker {
12389 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12391 Expr *
getV()
const {
return V; }
12392 Expr *
getR()
const {
return R; }
12397 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12400 bool checkType(ErrorInfoTy &ErrorInfo);
12412 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12416 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12428bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12429 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12432 if (
V && !CheckValue(
V, ErrorInfo,
true))
12435 if (R && !CheckValue(R, ErrorInfo,
true,
true))
12441bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
12442 ErrorInfoTy &ErrorInfo) {
12446 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12447 if (CS->body_empty()) {
12448 ErrorInfo.Error = ErrorTy::NoStmt;
12449 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12453 if (CS->size() > 1) {
12454 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12455 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12456 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12459 Then = CS->body_front();
12462 auto *BO = dyn_cast<BinaryOperator>(Then);
12464 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12465 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12466 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12469 if (BO->getOpcode() != BO_Assign) {
12470 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12471 ErrorInfo.ErrorLoc = BO->getExprLoc();
12472 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12473 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12480 auto *
Cond = dyn_cast<BinaryOperator>(S->
getCond());
12481 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
12482 Expr *LHS =
nullptr;
12483 Expr *RHS =
nullptr;
12485 LHS =
Cond->getLHS();
12486 RHS =
Cond->getRHS();
12488 LHS =
Call->getArg(0);
12489 RHS =
Call->getArg(1);
12491 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12496 if ((
Cond &&
Cond->getOpcode() != BO_EQ) ||
12497 (
Call &&
Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12498 ErrorInfo.Error = ErrorTy::NotEQ;
12504 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12506 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12509 ErrorInfo.Error = ErrorTy::InvalidComparison;
12518 ErrorInfo.Error = ErrorTy::NoElse;
12519 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12520 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12525 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12526 if (CS->body_empty()) {
12527 ErrorInfo.Error = ErrorTy::NoStmt;
12528 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12532 if (CS->size() > 1) {
12533 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12534 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12535 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12538 Else = CS->body_front();
12541 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12543 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12544 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12545 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12548 if (ElseBO->getOpcode() != BO_Assign) {
12549 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12550 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12551 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12552 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12556 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12557 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12558 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12559 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12560 ElseBO->getRHS()->getSourceRange();
12564 V = ElseBO->getLHS();
12566 return checkType(ErrorInfo);
12569bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12570 ErrorInfoTy &ErrorInfo) {
12574 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12577 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12579 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12580 ErrorInfo.Error = ErrorTy::InvalidCondition;
12581 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12582 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12588 auto *Then = S2->getThen();
12589 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12590 if (ThenCS->body_empty()) {
12591 ErrorInfo.Error = ErrorTy::NoStmt;
12592 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12593 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12596 if (ThenCS->size() > 1) {
12597 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12598 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12599 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12602 Then = ThenCS->body_front();
12605 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12607 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12608 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12609 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12612 if (ThenBO->getOpcode() != BO_Assign) {
12613 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12614 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12615 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12616 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12620 X = ThenBO->getLHS();
12621 D = ThenBO->getRHS();
12624 if (BO->getOpcode() != BO_EQ) {
12625 ErrorInfo.Error = ErrorTy::NotEQ;
12626 ErrorInfo.ErrorLoc = BO->getExprLoc();
12627 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12628 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12634 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12636 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12639 ErrorInfo.Error = ErrorTy::InvalidComparison;
12640 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12641 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12645 if (S2->getElse()) {
12648 auto *Else = S2->getElse();
12649 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12650 if (ElseCS->body_empty()) {
12651 ErrorInfo.Error = ErrorTy::NoStmt;
12652 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12653 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12656 if (ElseCS->size() > 1) {
12657 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12658 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12659 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12662 Else = ElseCS->body_front();
12665 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12667 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12668 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12669 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12672 if (ElseBO->getOpcode() != BO_Assign) {
12673 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12674 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12675 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12676 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12679 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12680 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12681 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12682 ErrorInfo.NoteLoc =
X->getExprLoc();
12683 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12684 ErrorInfo.NoteRange =
X->getSourceRange();
12688 V = ElseBO->getLHS();
12691 return checkType(ErrorInfo);
12694bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12695 ErrorInfoTy &ErrorInfo) {
12697 if (
auto *IS = dyn_cast<IfStmt>(S))
12698 return checkForm3(IS, ErrorInfo);
12700 auto *CS = dyn_cast<CompoundStmt>(S);
12702 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12703 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
12704 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
12707 if (CS->body_empty()) {
12708 ErrorInfo.Error = ErrorTy::NoStmt;
12709 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12710 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12715 if (CS->size() == 1) {
12716 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12718 ErrorInfo.Error = ErrorTy::NotIfStmt;
12719 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12720 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12725 return checkForm3(IS, ErrorInfo);
12726 }
else if (CS->size() == 2) {
12727 auto *S1 = CS->body_front();
12728 auto *S2 = CS->body_back();
12730 Stmt *UpdateStmt =
nullptr;
12731 Stmt *CondUpdateStmt =
nullptr;
12732 Stmt *CondExprStmt =
nullptr;
12734 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12744 return checkForm45(CS, ErrorInfo);
12753 CondUpdateStmt = S2;
12762 CondUpdateStmt = S1;
12765 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12766 auto *IS = dyn_cast<IfStmt>(CUS);
12768 ErrorInfo.Error = ErrorTy::NotIfStmt;
12769 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12770 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12774 return checkCondUpdateStmt(IS, ErrorInfo);
12778 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12779 auto *BO = dyn_cast<BinaryOperator>(US);
12781 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12786 if (BO->getOpcode() != BO_Assign) {
12787 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12788 ErrorInfo.ErrorLoc = BO->getExprLoc();
12789 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12790 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12793 if (!checkIfTwoExprsAreSame(ContextRef, this->
X, BO->getRHS())) {
12794 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12795 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12796 ErrorInfo.NoteLoc = this->
X->getExprLoc();
12797 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12798 ErrorInfo.NoteRange = this->
X->getSourceRange();
12802 this->
V = BO->getLHS();
12807 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12809 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12811 if (!CheckUpdateStmt(UpdateStmt))
12814 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12815 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12816 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12820 return checkType(ErrorInfo);
12831 DSAStack->addAtomicDirectiveLoc(StartLoc);
12844 bool MutexClauseEncountered =
false;
12845 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12847 switch (
C->getClauseKind()) {
12851 MutexClauseEncountered =
true;
12854 case OMPC_compare: {
12855 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12856 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12858 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12861 AtomicKind =
C->getClauseKind();
12862 AtomicKindLoc =
C->getBeginLoc();
12863 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12864 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12866 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12874 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12875 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12886 case OMPC_relaxed: {
12887 if (MemOrderKind != OMPC_unknown) {
12888 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12889 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12891 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12894 MemOrderKind =
C->getClauseKind();
12895 MemOrderLoc =
C->getBeginLoc();
12903 llvm_unreachable(
"unknown clause is encountered");
12906 bool IsCompareCapture =
false;
12907 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12908 EncounteredAtomicKinds.contains(OMPC_capture)) {
12909 IsCompareCapture =
true;
12910 AtomicKind = OMPC_compare;
12919 if ((AtomicKind == OMPC_read &&
12920 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12921 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12922 AtomicKind == OMPC_unknown) &&
12923 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12925 if (AtomicKind == OMPC_unknown)
12927 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12929 << (AtomicKind == OMPC_unknown ? 1 : 0)
12931 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12935 Stmt *Body = AStmt;
12936 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12937 Body = EWC->getSubExpr();
12942 Expr *UE =
nullptr;
12944 Expr *CE =
nullptr;
12971 if (AtomicKind == OMPC_read) {
12978 } ErrorFound = NoError;
12983 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12984 const auto *AtomicBinOp =
12985 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12986 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12989 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12990 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12991 if (!
X->isLValue() || !
V->isLValue()) {
12992 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12993 ErrorFound = NotAnLValue;
12999 }
else if (!
X->isInstantiationDependent() ||
13000 !
V->isInstantiationDependent()) {
13001 const Expr *NotScalarExpr =
13002 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
13005 ErrorFound = NotAScalarType;
13011 }
else if (!AtomicBody->isInstantiationDependent()) {
13012 ErrorFound = NotAnAssignmentOp;
13013 ErrorLoc = AtomicBody->getExprLoc();
13014 ErrorRange = AtomicBody->getSourceRange();
13016 : AtomicBody->getExprLoc();
13018 : AtomicBody->getSourceRange();
13021 ErrorFound = NotAnExpression;
13023 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
13025 if (ErrorFound != NoError) {
13026 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
13028 Diag(NoteLoc, diag::note_omp_atomic_read_write)
13029 << ErrorFound << NoteRange;
13032 if (
SemaRef.CurContext->isDependentContext())
13034 }
else if (AtomicKind == OMPC_write) {
13041 } ErrorFound = NoError;
13046 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13047 const auto *AtomicBinOp =
13048 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13049 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
13051 E = AtomicBinOp->
getRHS();
13052 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
13054 if (!
X->isLValue()) {
13055 ErrorFound = NotAnLValue;
13058 NoteLoc =
X->getExprLoc();
13059 NoteRange =
X->getSourceRange();
13061 }
else if (!
X->isInstantiationDependent() ||
13063 const Expr *NotScalarExpr =
13064 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
13067 ErrorFound = NotAScalarType;
13073 }
else if (!AtomicBody->isInstantiationDependent()) {
13074 ErrorFound = NotAnAssignmentOp;
13075 ErrorLoc = AtomicBody->getExprLoc();
13076 ErrorRange = AtomicBody->getSourceRange();
13078 : AtomicBody->getExprLoc();
13080 : AtomicBody->getSourceRange();
13083 ErrorFound = NotAnExpression;
13085 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
13087 if (ErrorFound != NoError) {
13088 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
13090 Diag(NoteLoc, diag::note_omp_atomic_read_write)
13091 << ErrorFound << NoteRange;
13094 if (
SemaRef.CurContext->isDependentContext())
13096 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13105 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13106 if (Checker.checkStatement(
13108 (AtomicKind == OMPC_update)
13109 ? diag::err_omp_atomic_update_not_expression_statement
13110 : diag::err_omp_atomic_not_expression_statement,
13111 diag::note_omp_atomic_update))
13113 if (!
SemaRef.CurContext->isDependentContext()) {
13114 E = Checker.getExpr();
13115 X = Checker.getX();
13116 UE = Checker.getUpdateExpr();
13119 }
else if (AtomicKind == OMPC_capture) {
13122 NotACompoundStatement,
13123 NotTwoSubstatements,
13124 NotASpecificExpression,
13126 } ErrorFound = NoError;
13129 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13138 const auto *AtomicBinOp =
13139 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13140 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
13143 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13144 if (Checker.checkStatement(
13145 Body, diag::err_omp_atomic_capture_not_expression_statement,
13146 diag::note_omp_atomic_update))
13148 E = Checker.getExpr();
13149 X = Checker.getX();
13150 UE = Checker.getUpdateExpr();
13153 }
else if (!AtomicBody->isInstantiationDependent()) {
13154 ErrorLoc = AtomicBody->getExprLoc();
13155 ErrorRange = AtomicBody->getSourceRange();
13157 : AtomicBody->getExprLoc();
13159 : AtomicBody->getSourceRange();
13160 ErrorFound = NotAnAssignmentOp;
13162 if (ErrorFound != NoError) {
13163 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13165 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13168 if (
SemaRef.CurContext->isDependentContext())
13169 UE =
V = E =
X =
nullptr;
13187 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
13189 if (CS->size() == 2) {
13191 Stmt *Second = CS->body_back();
13192 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
13193 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13194 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13195 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13197 OpenMPAtomicUpdateChecker Checker(
SemaRef);
13198 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13200 if (IsUpdateExprFound) {
13201 BinOp = dyn_cast<BinaryOperator>(
First);
13202 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13204 if (IsUpdateExprFound && !
SemaRef.CurContext->isDependentContext()) {
13214 llvm::FoldingSetNodeID XId, PossibleXId;
13215 Checker.getX()->Profile(XId, Context,
true);
13216 PossibleX->
Profile(PossibleXId, Context,
true);
13217 IsUpdateExprFound = XId == PossibleXId;
13218 if (IsUpdateExprFound) {
13220 X = Checker.getX();
13221 E = Checker.getExpr();
13222 UE = Checker.getUpdateExpr();
13227 if (!IsUpdateExprFound) {
13228 IsUpdateExprFound = !Checker.checkStatement(
First);
13230 if (IsUpdateExprFound) {
13231 BinOp = dyn_cast<BinaryOperator>(Second);
13232 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
13234 if (IsUpdateExprFound &&
13235 !
SemaRef.CurContext->isDependentContext()) {
13245 llvm::FoldingSetNodeID XId, PossibleXId;
13246 Checker.getX()->Profile(XId, Context,
true);
13247 PossibleX->
Profile(PossibleXId, Context,
true);
13248 IsUpdateExprFound = XId == PossibleXId;
13249 if (IsUpdateExprFound) {
13251 X = Checker.getX();
13252 E = Checker.getExpr();
13253 UE = Checker.getUpdateExpr();
13259 if (!IsUpdateExprFound) {
13261 auto *FirstExpr = dyn_cast<Expr>(
First);
13262 auto *SecondExpr = dyn_cast<Expr>(Second);
13263 if (!FirstExpr || !SecondExpr ||
13264 !(FirstExpr->isInstantiationDependent() ||
13265 SecondExpr->isInstantiationDependent())) {
13266 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
13267 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13268 ErrorFound = NotAnAssignmentOp;
13269 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13270 :
First->getBeginLoc();
13271 NoteRange = ErrorRange = FirstBinOp
13272 ? FirstBinOp->getSourceRange()
13275 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13276 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13277 ErrorFound = NotAnAssignmentOp;
13278 NoteLoc = ErrorLoc = SecondBinOp
13279 ? SecondBinOp->getOperatorLoc()
13281 NoteRange = ErrorRange =
13282 SecondBinOp ? SecondBinOp->getSourceRange()
13285 Expr *PossibleXRHSInFirst =
13287 Expr *PossibleXLHSInSecond =
13289 llvm::FoldingSetNodeID X1Id, X2Id;
13290 PossibleXRHSInFirst->
Profile(X1Id, Context,
13292 PossibleXLHSInSecond->
Profile(X2Id, Context,
13294 IsUpdateExprFound = X1Id == X2Id;
13295 if (IsUpdateExprFound) {
13296 V = FirstBinOp->getLHS();
13297 X = SecondBinOp->getLHS();
13298 E = SecondBinOp->getRHS();
13303 ErrorFound = NotASpecificExpression;
13304 ErrorLoc = FirstBinOp->getExprLoc();
13305 ErrorRange = FirstBinOp->getSourceRange();
13306 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13307 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13315 NoteRange = ErrorRange =
13317 ErrorFound = NotTwoSubstatements;
13321 NoteRange = ErrorRange =
13323 ErrorFound = NotACompoundStatement;
13326 if (ErrorFound != NoError) {
13327 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13329 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13332 if (
SemaRef.CurContext->isDependentContext())
13333 UE =
V = E =
X =
nullptr;
13334 }
else if (AtomicKind == OMPC_compare) {
13335 if (IsCompareCapture) {
13336 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13337 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
13338 if (!Checker.checkStmt(Body, ErrorInfo)) {
13339 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13340 << ErrorInfo.ErrorRange;
13341 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13342 << ErrorInfo.Error << ErrorInfo.NoteRange;
13345 X = Checker.getX();
13346 E = Checker.getE();
13347 D = Checker.getD();
13348 CE = Checker.getCond();
13349 V = Checker.getV();
13350 R = Checker.getR();
13356 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13357 OpenMPAtomicCompareChecker Checker(
SemaRef);
13358 if (!Checker.checkStmt(Body, ErrorInfo)) {
13359 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13360 << ErrorInfo.ErrorRange;
13361 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13362 << ErrorInfo.Error << ErrorInfo.NoteRange;
13365 X = Checker.getX();
13366 E = Checker.getE();
13367 D = Checker.getD();
13368 CE = Checker.getCond();
13374 auto *It = find_if(Clauses, [](
OMPClause *
C) {
13375 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13377 if (It != Clauses.end()) {
13378 auto *
Cond = dyn_cast<BinaryOperator>(CE);
13379 if (
Cond->getOpcode() != BO_EQ) {
13380 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13381 ErrorInfo.ErrorLoc =
Cond->getExprLoc();
13382 ErrorInfo.NoteLoc =
Cond->getOperatorLoc();
13383 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
Cond->getSourceRange();
13385 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13386 << ErrorInfo.ErrorRange;
13395 SemaRef.setFunctionHasBranchProtectedScope();
13397 return OMPAtomicDirective::Create(
13398 Context, StartLoc, EndLoc, Clauses, AStmt,
13415 if (
DSAStack->hasInnerTeamsRegion()) {
13417 bool OMPTeamsFound =
true;
13418 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
13419 auto I = CS->body_begin();
13420 while (I != CS->body_end()) {
13421 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13423 if (!IsTeams || I != CS->body_begin()) {
13424 OMPTeamsFound =
false;
13425 if (IsTeams && I != CS->body_begin()) {
13434 assert(I != CS->body_end() &&
"Not found statement");
13437 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13440 if (!OMPTeamsFound) {
13441 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13443 diag::note_omp_nested_teams_construct_here);
13476 OMPLoopBasedDirective::HelperExprs B;
13479 unsigned NestedLoopCount =
13482 VarsWithImplicitDSA, B);
13483 if (NestedLoopCount == 0)
13490 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13497 return llvm::any_of(
13498 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13501template <
typename... Params>
13503 const Params... ClauseTypes) {
13510 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13511 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13512 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13513 (VD->isExternallyVisible() &&
13514 VD->getVisibility() != HiddenVisibility);
13516 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13517 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13518 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13519 (VD->isExternallyVisible() &&
13520 VD->getVisibility() != HiddenVisibility);
13539 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13541 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13544 Expected =
"'map' or 'use_device_ptr'";
13546 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13548 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13549 <<
Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13553 SemaRef.setFunctionHasBranchProtectedScope();
13571 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13573 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13593 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13594 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13610 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13611 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13616 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13626template <
typename ClauseT>
13632 const uint64_t NumVars = Clause->getVarRefs().size();
13635 if (BareClause && NumVars > 3) {
13636 SemaRef.
Diag(Clause->getBeginLoc(),
13637 diag::err_ompx_more_than_three_expr_not_allowed)
13638 << getOpenMPClauseName(Clause->getClauseKind());
13643 if (!BareClause && NumVars != 1) {
13644 SemaRef.
Diag(Clause->getBeginLoc(), diag::err_omp_multi_expr_not_allowed)
13645 << getOpenMPClauseName(Clause->getClauseKind());
13656 bool MayHaveBareClause =
false) {
13657 auto BareClauseIt =
13658 MayHaveBareClause ? llvm::find_if(Clauses, llvm::IsaPred<OMPXBareClause>)
13660 auto ThreadLimitIt =
13661 llvm::find_if(Clauses, llvm::IsaPred<OMPThreadLimitClause>);
13662 auto NumTeamsIt = llvm::find_if(Clauses, llvm::IsaPred<OMPNumTeamsClause>);
13664 const auto *BareClause = BareClauseIt != Clauses.end()
13667 const auto *ThreadLimitClause =
13668 ThreadLimitIt != Clauses.end()
13671 const auto *NumTeamsClause = NumTeamsIt != Clauses.end()
13675 if (BareClause && (!NumTeamsClause || !ThreadLimitClause)) {
13676 SemaRef.
Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
13695 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13699 DSAStack->setParentTeamsRegionLoc(StartLoc);
13708 if (
DSAStack->isParentNowaitRegion()) {
13709 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13712 if (
DSAStack->isParentOrderedRegion()) {
13713 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13717 EndLoc, CancelRegion);
13723 if (
DSAStack->isParentNowaitRegion()) {
13724 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13727 if (
DSAStack->isParentOrderedRegion()) {
13728 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13731 DSAStack->setParentCancelRegion(
true);
13738 const OMPClause *ReductionClause =
nullptr;
13739 const OMPClause *NogroupClause =
nullptr;
13741 if (
C->getClauseKind() == OMPC_reduction) {
13742 ReductionClause =
C;
13747 if (
C->getClauseKind() == OMPC_nogroup) {
13749 if (ReductionClause)
13754 if (ReductionClause && NogroupClause) {
13755 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13770 OMPLoopBasedDirective::HelperExprs B;
13773 unsigned NestedLoopCount =
13776 *
DSAStack, VarsWithImplicitDSA, B);
13777 if (NestedLoopCount == 0)
13780 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13781 "omp for loop exprs were not built");
13787 {OMPC_grainsize, OMPC_num_tasks}))
13795 SemaRef.setFunctionHasBranchProtectedScope();
13797 NestedLoopCount, Clauses, AStmt, B,
13811 OMPLoopBasedDirective::HelperExprs B;
13814 unsigned NestedLoopCount =
13817 VarsWithImplicitDSA, B);
13818 if (NestedLoopCount == 0)
13828 {OMPC_grainsize, OMPC_num_tasks}))
13839 NestedLoopCount, Clauses, AStmt, B);
13849 OMPLoopBasedDirective::HelperExprs B;
13852 unsigned NestedLoopCount =
13855 *
DSAStack, VarsWithImplicitDSA, B);
13856 if (NestedLoopCount == 0)
13859 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13860 "omp for loop exprs were not built");
13866 {OMPC_grainsize, OMPC_num_tasks}))
13874 SemaRef.setFunctionHasBranchProtectedScope();
13876 NestedLoopCount, Clauses, AStmt, B,
13887 OMPLoopBasedDirective::HelperExprs B;
13890 unsigned NestedLoopCount =
13893 *
DSAStack, VarsWithImplicitDSA, B);
13894 if (NestedLoopCount == 0)
13897 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13898 "omp for loop exprs were not built");
13904 {OMPC_grainsize, OMPC_num_tasks}))
13912 SemaRef.setFunctionHasBranchProtectedScope();
13914 NestedLoopCount, Clauses, AStmt, B,
13928 OMPLoopBasedDirective::HelperExprs B;
13931 unsigned NestedLoopCount =
13934 VarsWithImplicitDSA, B);
13935 if (NestedLoopCount == 0)
13945 {OMPC_grainsize, OMPC_num_tasks}))
13956 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13969 OMPLoopBasedDirective::HelperExprs B;
13972 unsigned NestedLoopCount =
13975 VarsWithImplicitDSA, B);
13976 if (NestedLoopCount == 0)
13986 {OMPC_grainsize, OMPC_num_tasks}))
13997 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14009 OMPLoopBasedDirective::HelperExprs B;
14015 VarsWithImplicitDSA, B);
14016 if (NestedLoopCount == 0)
14019 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14020 "omp for loop exprs were not built");
14026 {OMPC_grainsize, OMPC_num_tasks}))
14035 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14048 OMPLoopBasedDirective::HelperExprs B;
14054 VarsWithImplicitDSA, B);
14055 if (NestedLoopCount == 0)
14058 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14059 "omp for loop exprs were not built");
14065 {OMPC_grainsize, OMPC_num_tasks}))
14074 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14085 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
14087 OMPLoopBasedDirective::HelperExprs B;
14093 VarsWithImplicitDSA, B);
14094 if (NestedLoopCount == 0)
14104 {OMPC_grainsize, OMPC_num_tasks}))
14115 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14125 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
14127 OMPLoopBasedDirective::HelperExprs B;
14133 VarsWithImplicitDSA, B);
14134 if (NestedLoopCount == 0)
14144 {OMPC_grainsize, OMPC_num_tasks}))
14155 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14165 OMPLoopBasedDirective::HelperExprs B;
14168 unsigned NestedLoopCount =
14172 if (NestedLoopCount == 0)
14175 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14176 "omp for loop exprs were not built");
14178 SemaRef.setFunctionHasBranchProtectedScope();
14180 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14181 return DistributeDirective;
14193 OMPLoopBasedDirective::HelperExprs B;
14199 VarsWithImplicitDSA, B);
14200 if (NestedLoopCount == 0)
14203 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14204 "omp for loop exprs were not built");
14207 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14218 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14220 OMPLoopBasedDirective::HelperExprs B;
14226 VarsWithImplicitDSA, B);
14227 if (NestedLoopCount == 0)
14237 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14249 OMPLoopBasedDirective::HelperExprs B;
14252 unsigned NestedLoopCount =
14256 if (NestedLoopCount == 0)
14266 NestedLoopCount, Clauses, AStmt, B);
14278 OMPLoopBasedDirective::HelperExprs B;
14284 VarsWithImplicitDSA, B);
14285 if (NestedLoopCount == 0)
14295 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14306 OMPLoopBasedDirective::HelperExprs B;
14309 unsigned NestedLoopCount =
14312 VarsWithImplicitDSA, B);
14313 if (NestedLoopCount == 0)
14323 NestedLoopCount, Clauses, AStmt, B);
14335 OMPLoopBasedDirective::HelperExprs B;
14338 unsigned NestedLoopCount =
14342 if (NestedLoopCount == 0)
14345 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14346 "omp teams distribute loop exprs were not built");
14348 DSAStack->setParentTeamsRegionLoc(StartLoc);
14351 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14363 OMPLoopBasedDirective::HelperExprs B;
14369 VarsWithImplicitDSA, B);
14370 if (NestedLoopCount == 0)
14379 DSAStack->setParentTeamsRegionLoc(StartLoc);
14382 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14392 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14394 OMPLoopBasedDirective::HelperExprs B;
14400 VarsWithImplicitDSA, B);
14401 if (NestedLoopCount == 0)
14410 DSAStack->setParentTeamsRegionLoc(StartLoc);
14413 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14423 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14425 OMPLoopBasedDirective::HelperExprs B;
14431 VarsWithImplicitDSA, B);
14433 if (NestedLoopCount == 0)
14436 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14437 "omp for loop exprs were not built");
14439 DSAStack->setParentTeamsRegionLoc(StartLoc);
14442 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14473 OMPLoopBasedDirective::HelperExprs B;
14479 VarsWithImplicitDSA, B);
14480 if (NestedLoopCount == 0)
14483 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14484 "omp target teams distribute loop exprs were not built");
14487 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14500 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14502 OMPLoopBasedDirective::HelperExprs B;
14508 VarsWithImplicitDSA, B);
14509 if (NestedLoopCount == 0)
14516 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14530 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14532 OMPLoopBasedDirective::HelperExprs B;
14535 unsigned NestedLoopCount =
14540 if (NestedLoopCount == 0)
14550 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14563 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14565 OMPLoopBasedDirective::HelperExprs B;
14571 VarsWithImplicitDSA, B);
14572 if (NestedLoopCount == 0)
14582 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14589 Stmt *Dir = Transform->getDirective();
14591#define STMT(CLASS, PARENT)
14592#define ABSTRACT_STMT(CLASS)
14593#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14594 case Stmt::CLASS##Class: \
14595 appendFlattenedStmtList(PreInits, \
14596 static_cast<const CLASS *>(Dir)->getPreInits()); \
14598#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14599 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14600#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14601 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14602#include "clang/AST/StmtNodes.inc"
14603#undef COMMON_OMP_LOOP_TRANSFORMATION
14605 llvm_unreachable(
"Not a loop transformation");
14609bool SemaOpenMP::checkTransformableLoopNest(
14613 OriginalInits.emplace_back();
14614 bool Result = OMPLoopBasedDirective::doForAllLoops(
14616 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14618 VarsWithInheritedDSAType TmpDSA;
14619 unsigned SingleNumLoops =
14620 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14621 TmpDSA, LoopHelpers[Cnt]);
14622 if (SingleNumLoops == 0)
14624 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14625 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14626 OriginalInits.back().push_back(For->getInit());
14627 Body = For->getBody();
14629 assert(isa<CXXForRangeStmt>(CurStmt) &&
14630 "Expected canonical for or range-based for loops.");
14631 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14632 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14633 Body = CXXFor->getBody();
14635 OriginalInits.emplace_back();
14638 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14641 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14642 OriginalInits.pop_back();
14680 unsigned NestedLoopCount = 0;
14727bool SemaOpenMP::analyzeLoopSequence(
Stmt *LoopSeqStmt,
14728 LoopSequenceAnalysis &SeqAnalysis,
14734 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14735 if (
auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14736 Analysis.OriginalInits.push_back(For->getInit());
14737 Analysis.TheForStmt = For;
14740 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14741 Analysis.TheForStmt = CXXFor;
14748 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14750 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14751 unsigned NumGeneratedTopLevelLoops =
14752 LoopTransform->getNumGeneratedTopLevelLoops();
14755 if (!TransformedStmt) {
14756 if (NumGeneratedTopLevelLoops > 0) {
14757 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14761 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14762 << 0 << getOpenMPDirectiveName(Kind);
14767 if (!NumGeneratedTopLevelLoops) {
14768 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14769 << 0 << getOpenMPDirectiveName(Kind);
14773 if (NumGeneratedTopLevelLoops > 1) {
14780 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14781 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14785 LoopAnalysis &NewTransformedSingleLoop =
14786 SeqAnalysis.Loops.emplace_back(Child);
14789 NewTransformedSingleLoop.HelperExprs);
14794 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14795 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14797 SeqAnalysis.LoopSeqSize++;
14802 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14803 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14804 unsigned IsCanonical =
14806 TmpDSA, NewRegularLoop.HelperExprs);
14811 StoreLoopStatements(NewRegularLoop, Child);
14812 NestedLoopCounterVisitor NLCV;
14818 for (Stmt *Child : LoopSeqStmt->
children()) {
14822 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14823 Child = Child->IgnoreContainers();
14830 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14837 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14838 if (LoopAnalysis::isLoopTransformation(Child)) {
14839 if (!AnalyzeLoopGeneration(Child))
14843 if (!AnalyzeRegularLoop(Child))
14845 SeqAnalysis.LoopSeqSize++;
14849 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14850 << 0 << getOpenMPDirectiveName(Kind);
14857bool SemaOpenMP::checkTransformableLoopSequence(
14882 << getOpenMPDirectiveName(Kind);
14887 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14891 if (!SeqAnalysis.LoopSeqSize) {
14893 << getOpenMPDirectiveName(Kind);
14901 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14907 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14908 Stmt *RangeInit = CXXRangeFor->getInit();
14910 PreInits.push_back(RangeInit);
14912 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14917 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14923 llvm::append_range(PreInits, OriginalInit);
14926 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14927 PreInits.push_back(
new (Context)
DeclStmt(
14928 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14932 for (
Expr *CounterRef : LoopHelper.Counters) {
14935 PreInits.push_back(
new (Context)
DeclStmt(
14943 size_t NumLoops = LoopStmts.size();
14944 OMPLoopBasedDirective::doForAllLoops(
14945 AStmt,
false, NumLoops,
14946 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14947 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14948 LoopStmts[Cnt] = CurStmt;
14951 assert(!is_contained(LoopStmts,
nullptr) &&
14952 "Expecting a loop statement for each affected loop");
14970 const auto *SizesClause =
14971 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14972 if (!SizesClause ||
14973 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *E) { return !E; }))
14975 unsigned NumLoops = SizesClause->getNumSizes();
14983 Stmt *Body =
nullptr;
14985 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14990 if (
SemaRef.CurContext->isDependentContext())
14992 NumLoops, AStmt,
nullptr,
nullptr);
14994 assert(LoopHelpers.size() == NumLoops &&
14995 "Expecting loop iteration space dimensionality to match number of "
14997 assert(OriginalInits.size() == NumLoops &&
14998 "Expecting loop iteration space dimensionality to match number of "
15006 CaptureVars CopyTransformer(
SemaRef);
15011 FloorIndVars.resize(NumLoops);
15012 TileIndVars.resize(NumLoops);
15013 for (
unsigned I = 0; I < NumLoops; ++I) {
15014 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15016 assert(LoopHelper.Counters.size() == 1 &&
15017 "Expect single-dimensional loop iteration space");
15019 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15025 std::string FloorCntName =
15026 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15029 FloorIndVars[I] = FloorCntDecl;
15034 std::string TileCntName =
15035 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15041 TileCntDecl->setDeclName(
15042 &
SemaRef.PP.getIdentifierTable().get(TileCntName));
15043 TileIndVars[I] = TileCntDecl;
15051 Stmt *Inner = Body;
15053 auto MakeDimTileSize = [&
SemaRef = this->SemaRef, &CopyTransformer, &Context,
15054 SizesClause, CurScope](
int I) ->
Expr * {
15055 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
15061 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
15080 uint64_t DimWidth = Context.getTypeSize(DimTy);
15082 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15086 CurScope, {}, BO_LE,
15090 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
15096 for (
int I = NumLoops - 1; I >= 0; --I) {
15097 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15098 Expr *NumIterations = LoopHelper.NumIterations;
15101 Stmt *LoopStmt = LoopStmts[I];
15106 auto MakeTileIVRef = [&
SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
15109 OrigCntVar->getExprLoc());
15113 SemaRef.AddInitializerToDecl(
15116 .DefaultLvalueConversion(
15120 Decl *CounterDecl = TileIndVars[I];
15123 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15129 Expr *DimTileSize = MakeDimTileSize(I);
15133 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15139 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15140 NumIterations, EndOfTile.
get());
15144 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15145 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
15146 if (!MinTileAndIterSpace.
isUsable())
15149 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15150 MakeTileIVRef(), MinTileAndIterSpace.
get());
15156 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15177 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15178 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15179 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15180 BodyParts.push_back(Inner);
15183 Inner =
new (Context)
15186 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15190 for (
int I = NumLoops - 1; I >= 0; --I) {
15191 auto &LoopHelper = LoopHelpers[I];
15192 Expr *NumIterations = LoopHelper.NumIterations;
15197 SemaRef.AddInitializerToDecl(
15199 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15201 Decl *CounterDecl = FloorIndVars[I];
15210 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15217 Expr *DimTileSize = MakeDimTileSize(I);
15221 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15227 Inner =
new (Context)
15230 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15245 const auto *SizesClause =
15246 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15247 if (!SizesClause ||
15248 llvm::any_of(SizesClause->getSizesRefs(), [](
const Expr *SizeExpr) {
15249 return !SizeExpr || SizeExpr->containsErrors();
15252 unsigned NumLoops = SizesClause->getNumSizes();
15260 Stmt *Body =
nullptr;
15262 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15263 Body, OriginalInits))
15267 if (
SemaRef.CurContext->isDependentContext())
15269 NumLoops, AStmt,
nullptr,
nullptr);
15271 assert(LoopHelpers.size() == NumLoops &&
15272 "Expecting loop iteration space dimensionality to match number of "
15274 assert(OriginalInits.size() == NumLoops &&
15275 "Expecting loop iteration space dimensionality to match number of "
15283 CaptureVars CopyTransformer(
SemaRef);
15288 FloorIndVars.resize(NumLoops);
15289 StripeIndVars.resize(NumLoops);
15290 for (
unsigned I : llvm::seq<unsigned>(NumLoops)) {
15291 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15293 assert(LoopHelper.Counters.size() == 1 &&
15294 "Expect single-dimensional loop iteration space");
15296 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15302 std::string FloorCntName =
15303 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15306 FloorIndVars[I] = FloorCntDecl;
15311 std::string StripeCntName =
15312 (Twine(
".stripe_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
15318 StripeCntDecl->setDeclName(
15319 &
SemaRef.PP.getIdentifierTable().get(StripeCntName));
15320 StripeIndVars[I] = StripeCntDecl;
15328 Stmt *Inner = Body;
15330 auto MakeDimStripeSize = [&](
int I) ->
Expr * {
15331 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15333 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15352 uint64_t DimWidth = Context.getTypeSize(DimTy);
15354 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15358 CurScope, {}, BO_LE,
15362 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15368 for (
int I = NumLoops - 1; I >= 0; --I) {
15369 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15370 Expr *NumIterations = LoopHelper.NumIterations;
15373 Stmt *LoopStmt = LoopStmts[I];
15376 SemaRef.AddInitializerToDecl(
15379 .DefaultLvalueConversion(
15383 Decl *CounterDecl = StripeIndVars[I];
15386 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15393 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15395 MakeDimStripeSize(I));
15399 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15400 NumIterations, EndOfStripe.
get());
15404 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15405 IsPartialStripe.
get(), NumIterations, EndOfStripe.
get());
15406 if (!MinStripeAndIterSpace.
isUsable())
15409 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15411 MinStripeAndIterSpace.
get());
15417 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15439 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15440 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15441 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15442 BodyParts.push_back(Inner);
15445 Inner =
new (Context)
15448 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15452 for (
int I = NumLoops - 1; I >= 0; --I) {
15453 auto &LoopHelper = LoopHelpers[I];
15454 Expr *NumIterations = LoopHelper.NumIterations;
15459 SemaRef.AddInitializerToDecl(
15461 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15463 Decl *CounterDecl = FloorIndVars[I];
15472 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15480 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15482 MakeDimStripeSize(I));
15486 Inner =
new (Context)
15489 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15493 NumLoops, AStmt, Inner,
15508 {OMPC_partial, OMPC_full}))
15512 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15514 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15515 assert(!(FullClause && PartialClause) &&
15516 "mutual exclusivity must have been checked before");
15518 constexpr unsigned NumLoops = 1;
15519 Stmt *Body =
nullptr;
15523 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15524 Body, OriginalInits))
15527 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15530 if (
SemaRef.CurContext->isDependentContext())
15532 NumGeneratedTopLevelLoops,
nullptr,
15535 assert(LoopHelpers.size() == NumLoops &&
15536 "Expecting a single-dimensional loop iteration space");
15537 assert(OriginalInits.size() == NumLoops &&
15538 "Expecting a single-dimensional loop iteration space");
15539 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15543 LoopHelper.NumIterations, OMPC_full,
false,
15546 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15548 <<
"#pragma omp unroll full";
15556 if (NumGeneratedTopLevelLoops == 0)
15558 NumGeneratedTopLevelLoops,
nullptr,
15604 Stmt *LoopStmt =
nullptr;
15609 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15612 QualType IVTy = IterationVarRef->getType();
15613 assert(LoopHelper.Counters.size() == 1 &&
15614 "Expecting a single-dimensional loop iteration space");
15622 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15623 FactorLoc = FactorVal->getExprLoc();
15628 assert(Factor > 0 &&
"Expected positive unroll factor");
15629 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
15641 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15642 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
15643 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
15648 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
15654 auto *InnerIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15655 InnerIVDecl->setDeclName(&
SemaRef.PP.getIdentifierTable().get(InnerIVName));
15656 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
15662 CaptureVars CopyTransformer(
SemaRef);
15663 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15665 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15670 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.
get(),
15685 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15686 MakeOuterRef(), MakeFactorExpr());
15690 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15691 MakeInnerRef(), EndOfTile.
get());
15695 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15696 MakeInnerRef(), MakeNumIterations());
15700 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15701 InnerCond1.
get(), InnerCond2.
get());
15707 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15713 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15714 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15715 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15716 InnerBodyStmts.push_back(Body);
15720 ForStmt *InnerFor =
new (Context)
15721 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
15723 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15737 LoopHintAttr *UnrollHintAttr =
15738 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15739 LoopHintAttr::Numeric, MakeFactorExpr());
15744 SemaRef.AddInitializerToDecl(
15746 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15755 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15756 MakeOuterRef(), MakeNumIterations());
15762 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15763 MakeOuterRef(), MakeFactorExpr());
15768 ForStmt *OuterFor =
new (Context)
15769 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
15771 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15774 NumGeneratedTopLevelLoops, OuterFor,
15788 constexpr unsigned NumLoops = 1;
15789 Stmt *Body =
nullptr;
15793 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15794 Body, OriginalInits))
15799 if (
SemaRef.CurContext->isDependentContext())
15801 NumLoops,
nullptr,
nullptr);
15803 assert(LoopHelpers.size() == NumLoops &&
15804 "Expecting a single-dimensional loop iteration space");
15805 assert(OriginalInits.size() == NumLoops &&
15806 "Expecting a single-dimensional loop iteration space");
15807 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15810 Stmt *LoopStmt =
nullptr;
15815 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15818 QualType IVTy = IterationVarRef->getType();
15819 uint64_t IVWidth = Context.getTypeSize(IVTy);
15833 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15835 ForwardIVName += OrigVarName;
15837 ReversedIVName += OrigVarName;
15870 CaptureVars CopyTransformer(
SemaRef);
15871 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15873 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15879 auto MakeForwardRef = [&
SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15886 auto *ReversedIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
15887 ReversedIVDecl->setDeclName(
15888 &
SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15895 ForwardIVDecl->
getType(), OrigVarLoc);
15896 SemaRef.AddInitializerToDecl(ForwardIVDecl,
Zero,
false);
15899 if (!
Init.isUsable())
15907 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15908 MakeForwardRef(), MakeNumIterations());
15909 if (!
Cond.isUsable())
15917 UO_PreInc, MakeForwardRef());
15928 MakeNumIterations(), One);
15931 Minus =
SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.
get(),
15936 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15939 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.
get(),
15944 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15946 BodyStmts.push_back(InitReversed.
get());
15947 llvm::append_range(BodyStmts, LoopHelper.Updates);
15948 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15949 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15950 BodyStmts.push_back(Body);
15951 auto *ReversedBody =
15956 auto *ReversedFor =
new (Context)
15959 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15980 const auto *CountsClause =
15981 OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
15986 constexpr unsigned NumLoops = 1;
15987 Stmt *Body =
nullptr;
15991 if (!checkTransformableLoopNest(OMPD_split, AStmt, NumLoops, LoopHelpers,
15992 Body, OriginalInits))
15997 if (
SemaRef.CurContext->isDependentContext())
15999 NumLoops, AStmt,
nullptr,
nullptr);
16001 assert(LoopHelpers.size() == NumLoops &&
16002 "Expecting a single-dimensional loop iteration space");
16003 assert(OriginalInits.size() == NumLoops &&
16004 "Expecting a single-dimensional loop iteration space");
16005 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16008 Stmt *LoopStmt =
nullptr;
16013 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
16018 QualType IVTy = IterationVarRef->getType();
16019 uint64_t IVWidth = Context.getTypeSize(IVTy);
16027 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16029 if (!CountsClause->hasOmpFill())
16031 unsigned FillIdx = *CountsClause->getOmpFillIndex();
16033 unsigned NumItems = CountsClause->getNumCounts();
16036 for (
unsigned I = 0; I < NumItems; ++I) {
16039 Expr *CountExpr = Refs[I];
16042 NumLoops, AStmt,
nullptr,
nullptr);
16043 std::optional<llvm::APSInt> OptVal =
16045 if (!OptVal || OptVal->isNegative())
16047 NumLoops, AStmt,
nullptr,
nullptr);
16048 CountValues[I] = OptVal->getZExtValue();
16051 Expr *NumIterExpr = LoopHelper.NumIterations;
16053 uint64_t RightSum = 0;
16054 for (
unsigned I = FillIdx + 1; I < NumItems; ++I)
16055 RightSum += CountValues[I];
16057 auto MakeIntLit = [&](uint64_t Val) {
16062 size_t NumSegments = NumItems;
16065 auto *IterVarDecl =
cast<VarDecl>(IterationVarRef->getDecl());
16067 IterationVarRef->getBeginLoc(),
16068 IterationVarRef->getEndLoc()));
16070 uint64_t LeftAccum = 0;
16071 uint64_t RightRemaining = RightSum;
16073 for (
size_t Seg = 0; Seg < NumSegments; ++Seg) {
16074 Expr *StartExpr =
nullptr;
16075 Expr *EndExpr =
nullptr;
16077 if (Seg < FillIdx) {
16078 StartExpr = MakeIntLit(LeftAccum);
16079 LeftAccum += CountValues[Seg];
16080 EndExpr = MakeIntLit(LeftAccum);
16081 }
else if (Seg == FillIdx) {
16082 StartExpr = MakeIntLit(LeftAccum);
16083 if (RightRemaining == 0) {
16084 EndExpr = NumIterExpr;
16087 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
16088 MakeIntLit(RightRemaining));
16089 if (!Sub.isUsable())
16091 EndExpr = Sub.get();
16094 if (RightRemaining == RightSum) {
16096 StartExpr = NumIterExpr;
16099 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
16100 MakeIntLit(RightRemaining));
16101 if (!Sub.isUsable())
16103 StartExpr = Sub.get();
16107 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
16108 MakeIntLit(RightRemaining));
16109 if (!Sub.isUsable())
16111 StartExpr = Sub.get();
16113 RightRemaining -= CountValues[Seg];
16114 if (RightRemaining == 0)
16115 EndExpr = NumIterExpr;
16118 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
16119 MakeIntLit(RightRemaining));
16120 if (!Sub.isUsable())
16122 EndExpr = Sub.get();
16127 IVName += (Twine(Seg) +
"." + OrigVarName).str();
16129 auto MakeIVRef = [&
SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
16133 SemaRef.AddInitializerToDecl(IVDecl, StartExpr,
false);
16140 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeIVRef(), EndExpr);
16145 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeIVRef());
16150 IterationVarRef, MakeIVRef());
16155 BodyStmts.push_back(IVAssign.
get());
16156 BodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
16157 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
16159 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
16161 VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
16166 CurScope, OrigVarLoc, BO_Assign, LVRef, LoopVar->
getInit());
16169 BodyStmts.push_back(LVAssign.
get());
16172 BodyStmts.push_back(Body);
16178 auto *For =
new (Context)
16181 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16182 SplitLoops.push_back(For);
16187 SplitLoops.front()->getBeginLoc(), SplitLoops.back()->getEndLoc());
16207 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
16208 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
16212 Stmt *Body =
nullptr;
16214 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
16215 LoopHelpers, Body, OriginalInits))
16221 NumLoops, AStmt,
nullptr,
nullptr);
16225 if (PermutationClause &&
16226 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
16229 assert(LoopHelpers.size() == NumLoops &&
16230 "Expecting loop iteration space dimensionaly to match number of "
16232 assert(OriginalInits.size() == NumLoops &&
16233 "Expecting loop iteration space dimensionaly to match number of "
16238 if (!PermutationClause) {
16239 Permutation = {1, 0};
16242 llvm::BitVector Flags(PermArgs.size());
16243 for (
Expr *PermArg : PermArgs) {
16244 std::optional<llvm::APSInt> PermCstExpr =
16245 PermArg->getIntegerConstantExpr(Context);
16248 uint64_t PermInt = PermCstExpr->getZExtValue();
16249 assert(1 <= PermInt && PermInt <= NumLoops &&
16250 "Must be a permutation; diagnostic emitted in "
16251 "ActOnOpenMPPermutationClause");
16252 if (Flags[PermInt - 1]) {
16253 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
16254 Diag(PermArg->getExprLoc(),
16255 diag::err_omp_interchange_permutation_value_repeated)
16256 << PermInt << ExprRange;
16259 Flags[PermInt - 1] =
true;
16261 Permutation.push_back(PermInt - 1);
16264 if (Permutation.size() != NumLoops)
16269 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
16270 auto [Idx, Arg] = P;
16274 NumLoops, AStmt, AStmt,
nullptr);
16282 for (
auto I : llvm::seq<int>(NumLoops)) {
16283 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16285 assert(LoopHelper.Counters.size() == 1 &&
16286 "Single-dimensional loop iteration space expected");
16293 CaptureVars CopyTransformer(
SemaRef);
16298 Stmt *Inner = Body;
16299 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
16301 uint64_t SourceIdx = Permutation[TargetIdx];
16302 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
16303 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
16304 assert(SourceHelper.Counters.size() == 1 &&
16305 "Single-dimensional loop iteration space expected");
16312 "Expected the logical iteration counter to be an integer");
16314 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16319 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
16321 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
16328 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
16330 PermutedCntDecl->setDeclName(
16331 &
SemaRef.PP.getIdentifierTable().get(PermutedCntName));
16332 PermutedIndVars[TargetIdx] = PermutedCntDecl;
16333 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
16342 if (!
Zero.isUsable())
16344 SemaRef.AddInitializerToDecl(PermutedCntDecl,
Zero.get(),
16348 OrigCntVar->getEndLoc());
16357 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
16358 MakePermutedRef(), MakeNumIterations());
16367 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
16372 SourceHelper.Updates.end());
16373 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
16374 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16375 BodyParts.push_back(Inner);
16378 Inner =
new (Context)
ForStmt(
16379 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
16380 SourceHelper.Init->
getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16381 SourceHelper.Inc->getEndLoc());
16385 NumLoops, AStmt, Inner,
16397 CaptureVars CopyTransformer(
SemaRef);
16409 1, AStmt,
nullptr,
nullptr);
16413 LoopSequenceAnalysis SeqAnalysis;
16414 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16419 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16420 "Inconsistent size of the loop sequence and the number of loops "
16421 "found in the sequence");
16425 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16429 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16434 auto EvaluateLoopRangeArguments = [&Context](
Expr *
First,
Expr *Count,
16435 uint64_t &FirstVal,
16436 uint64_t &CountVal) {
16437 llvm::APSInt FirstInt =
First->EvaluateKnownConstInt(Context);
16438 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16439 FirstVal = FirstInt.getZExtValue();
16440 CountVal = CountInt.getZExtValue();
16446 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16447 unsigned NumLoops) ->
bool {
16448 return FirstVal + CountVal - 1 <= NumLoops;
16450 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16456 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16459 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16460 << getOpenMPDirectiveName(OMPD_fuse);
16462 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16463 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16464 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16465 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16469 LastVal = FirstVal + CountVal - 1;
16474 unsigned NumGeneratedTopLevelLoops =
16475 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16479 if (SeqAnalysis.LoopSeqSize == 1)
16481 << getOpenMPDirectiveName(OMPD_fuse);
16485 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16486 for (
unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16488 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16489 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16490 IVType = CurrentIVType;
16493 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16506 auto CreateHelperVarAndStmt =
16508 unsigned I,
bool NeedsNewVD =
false) {
16509 Expr *TransformedExpr =
16511 if (!TransformedExpr)
16512 return std::pair<VarDecl *, StmtResult>(
nullptr,
StmtError());
16514 auto Name = (Twine(
".omp.") + BaseName + std::to_string(I)).str();
16519 SemaRef.AddInitializerToDecl(VD, TransformedExpr,
false);
16529 return std::make_pair(VD,
DeclStmt);
16547 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16560 unsigned int TransformIndex = 0;
16561 for (
unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16562 if (SeqAnalysis.Loops[I].isLoopTransformation())
16566 for (
unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16567 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16569 SeqAnalysis.Loops[I].TheForStmt,
16570 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16571 }
else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16576 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16577 llvm::append_range(PreInits, TransformPreInit);
16580 SeqAnalysis.Loops[I].TheForStmt,
16581 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16583 auto [UBVD, UBDStmt] =
16584 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB,
"ub", J);
16585 auto [LBVD, LBDStmt] =
16586 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB,
"lb", J);
16587 auto [STVD, STDStmt] =
16588 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST,
"st", J);
16589 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16590 SeqAnalysis.Loops[I].HelperExprs.NumIterations,
"ni", J,
true);
16591 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16592 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef,
"iv", J);
16594 assert(LBVD && STVD && NIVD && IVVD &&
16595 "OpenMP Fuse Helper variables creation failed");
16597 UBVarDecls.push_back(UBVD);
16598 LBVarDecls.push_back(LBVD);
16599 STVarDecls.push_back(STVD);
16600 NIVarDecls.push_back(NIVD);
16601 IVVarDecls.push_back(IVVD);
16603 PreInits.push_back(LBDStmt.get());
16604 PreInits.push_back(STDStmt.get());
16605 PreInits.push_back(NIDStmt.get());
16606 PreInits.push_back(IVDStmt.get());
16639 StringRef IndexName =
".omp.fuse.index";
16644 SemaRef.AddInitializerToDecl(IndexDecl, InitVal,
false);
16651 auto MakeIVRef = [&
SemaRef = this->SemaRef, IndexDecl, IVType,
16669 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16670 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16678 std::string TempName = (Twine(
".omp.temp.") + Twine(J)).str();
16692 PreInits.push_back(TempStmt.
get());
16701 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16715 const std::string MaxName = Twine(
".omp.fuse.max").str();
16723 if (MaxStmt.isInvalid())
16725 PreInits.push_back(MaxStmt.get());
16729 MakeIVRef(), MaxRef);
16755 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16760 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16764 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.
get());
16769 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.
get());
16775 BodyStmts.push_back(IdxExpr.
get());
16776 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16779 if (
auto *SourceCXXFor =
16780 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16781 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16785 ?
cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16787 BodyStmts.push_back(Body);
16794 MakeVarDeclRef(NIVarDecls[J]));
16804 FusedBodyStmts.push_back(IfStatement);
16810 ForStmt *FusedForStmt =
new (Context)
16824 Stmt *FusionStmt = FusedForStmt;
16825 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16829 TransformIndex = 0;
16835 for (
unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16836 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16839 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16848 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16849 const auto &TransformPreInit =
16850 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16851 if (!TransformPreInit.empty())
16852 llvm::append_range(PreInits, TransformPreInit);
16855 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16858 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16863 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16883 case OMPC_allocator:
16886 case OMPC_collapse:
16895 case OMPC_priority:
16907 case OMPC_novariants:
16910 case OMPC_nocontext:
16925 case OMPC_ompx_dyn_cgroup_mem:
16931 case OMPC_transparent:
16934 case OMPC_dyn_groupprivate:
16935 case OMPC_grainsize:
16936 case OMPC_num_tasks:
16937 case OMPC_num_threads:
16941 case OMPC_proc_bind:
16942 case OMPC_schedule:
16944 case OMPC_firstprivate:
16945 case OMPC_lastprivate:
16947 case OMPC_reduction:
16948 case OMPC_task_reduction:
16949 case OMPC_in_reduction:
16953 case OMPC_copyprivate:
16955 case OMPC_mergeable:
16956 case OMPC_threadprivate:
16957 case OMPC_groupprivate:
16959 case OMPC_allocate:
16976 case OMPC_dist_schedule:
16977 case OMPC_defaultmap:
16982 case OMPC_use_device_ptr:
16983 case OMPC_use_device_addr:
16984 case OMPC_is_device_ptr:
16985 case OMPC_unified_address:
16986 case OMPC_unified_shared_memory:
16987 case OMPC_reverse_offload:
16988 case OMPC_dynamic_allocators:
16989 case OMPC_atomic_default_mem_order:
16990 case OMPC_self_maps:
16991 case OMPC_device_type:
16993 case OMPC_nontemporal:
16996 case OMPC_severity:
16998 case OMPC_inclusive:
16999 case OMPC_exclusive:
17000 case OMPC_uses_allocators:
17001 case OMPC_affinity:
17004 case OMPC_num_teams:
17005 case OMPC_thread_limit:
17007 llvm_unreachable(
"Clause is not allowed.");
17020 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
17021 "Invalid directive with CKind-clause");
17024 if (NameModifier != OMPD_unknown &&
17025 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
17026 return OMPD_unknown;
17045 case OMPD_teams_loop:
17046 case OMPD_target_teams_loop:
17050 case OMPD_target_update:
17051 case OMPD_target_enter_data:
17052 case OMPD_target_exit_data:
17058 case OMPC_num_teams:
17059 case OMPC_thread_limit:
17060 case OMPC_ompx_dyn_cgroup_mem:
17061 case OMPC_dyn_groupprivate:
17063 if (Leafs[0] == OMPD_target)
17064 return OMPD_target;
17067 if (Leafs[0] == OMPD_target ||
17068 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
17069 OMPD_target_enter_data, OMPD_target_exit_data},
17073 case OMPC_novariants:
17074 case OMPC_nocontext:
17075 if (DKind == OMPD_dispatch)
17079 if (DKind == OMPD_metadirective)
17080 return OMPD_metadirective;
17083 return OMPD_unknown;
17096 int InnermostIdx = [&]() {
17097 for (
int I = EndIdx - 1; I >= 0; --I) {
17098 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
17106 for (
int I = InnermostIdx - 1; I >= 0; --I) {
17111 if (Regions[0] != OMPD_unknown)
17112 return Regions.back();
17114 return OMPD_unknown;
17119 for (
int I = 0, E = Leafs.size(); I != E; ++I) {
17120 if (Leafs[I] == Dir)
17126 int End = NameModifier == OMPD_unknown ? Leafs.size()
17127 : GetLeafIndex(NameModifier);
17128 return GetEnclosingRegion(End, CKind);
17131 return OMPD_unknown;
17139 Stmt *HelperValStmt =
nullptr;
17142 !
Condition->isInstantiationDependent() &&
17143 !
Condition->containsUnexpandedParameterPack()) {
17148 ValExpr = Val.
get();
17152 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
17153 if (CaptureRegion != OMPD_unknown &&
17154 !
SemaRef.CurContext->isDependentContext()) {
17155 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17156 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17157 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17163 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
17164 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
17172 Stmt *HelperValStmt =
nullptr;
17175 !
Condition->isInstantiationDependent() &&
17176 !
Condition->containsUnexpandedParameterPack()) {
17181 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
17186 if (CaptureRegion != OMPD_unknown &&
17187 !
SemaRef.CurContext->isDependentContext()) {
17188 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17189 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17190 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17196 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17207 IntConvertDiagnoser()
17208 : ICEConvertDiagnoser(
false,
false,
true) {}
17211 return S.
Diag(Loc, diag::err_omp_not_integral) << T;
17215 return S.
Diag(Loc, diag::err_omp_incomplete_type) << T;
17220 return S.
Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
17229 return S.
Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
17238 llvm_unreachable(
"conversion functions are permitted");
17240 } ConvertDiagnoser;
17241 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
17246 bool StrictlyPositive,
bool BuildCapture =
false,
17249 Stmt **HelperValStmt =
nullptr) {
17255 if (
Value.isInvalid())
17258 ValExpr =
Value.get();
17260 if (std::optional<llvm::APSInt>
Result =
17262 if (
Result->isSigned() &&
17263 !((!StrictlyPositive &&
Result->isNonNegative()) ||
17264 (StrictlyPositive &&
Result->isStrictlyPositive()))) {
17265 SemaRef.
Diag(Loc, diag::err_omp_negative_expression_in_clause)
17275 if (*CaptureRegion != OMPD_unknown &&
17278 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17279 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17290 llvm::raw_svector_ostream
Out(Buffer);
17291 unsigned Skipped = Exclude.size();
17292 for (
unsigned I =
First; I <
Last; ++I) {
17293 if (llvm::is_contained(Exclude, I)) {
17298 if (I + Skipped + 2 ==
Last)
17300 else if (I + Skipped + 1 !=
Last)
17303 return std::string(
Out.str());
17311 "Unexpected num_threads modifier in OpenMP < 60.");
17316 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
17321 Expr *ValExpr = NumThreads;
17322 Stmt *HelperValStmt =
nullptr;
17333 if (CaptureRegion != OMPD_unknown &&
17334 !
SemaRef.CurContext->isDependentContext()) {
17335 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
17336 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17337 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17343 StartLoc, LParenLoc, ModifierLoc, EndLoc);
17348 bool SuppressExprDiags) {
17357 if (SuppressExprDiags) {
17361 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
17364 llvm_unreachable(
"Diagnostic suppressed");
17367 ICE =
SemaRef.VerifyIntegerConstantExpression(E, &
Result, Diagnoser,
17377 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
17378 (!StrictlyPositive && !
Result.isNonNegative())) {
17379 Diag(E->
getExprLoc(), diag::err_omp_negative_expression_in_clause)
17384 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17385 CKind == OMPC_allocate) &&
17387 Diag(E->
getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
17392 if (!
Result.isRepresentableByInt64()) {
17398 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
17400 else if (CKind == OMPC_ordered)
17419 if (
Result.isNonNegative()) {
17423 diag::err_omp_negative_expression_in_clause)
17426 }
else if (
auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17433 Diag(DeviceNumExpr->
getExprLoc(), diag::err_expected_expression);
17467 DSAStackTy *Stack) {
17468 if (!Stack->getOMPAllocatorHandleT().isNull())
17475 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17476 <<
"omp_allocator_handle_t";
17481 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17484 bool ErrorFound =
false;
17485 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17486 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
17487 StringRef Allocator =
17488 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17490 auto *VD = dyn_cast_or_null<ValueDecl>(
17510 Stack->setAllocator(AllocatorKind, Res.
get());
17513 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
17514 <<
"omp_allocator_handle_t";
17533 Allocator =
SemaRef.PerformImplicitConversion(
17534 Allocator.
get(),
DSAStack->getOMPAllocatorHandleT(),
17563 Expr *NumForLoops) {
17569 if (NumForLoops && LParenLoc.
isValid()) {
17574 NumForLoops = NumForLoopsResult.
get();
17576 NumForLoops =
nullptr;
17580 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
17581 StartLoc, LParenLoc, EndLoc);
17582 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
17591 case OMPC_proc_bind:
17593 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17595 case OMPC_atomic_default_mem_order:
17598 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17602 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17606 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17610 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17614 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17616 case OMPC_severity:
17619 LParenLoc, EndLoc);
17621 case OMPC_threadset:
17623 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17627 case OMPC_num_threads:
17631 case OMPC_allocator:
17632 case OMPC_collapse:
17633 case OMPC_schedule:
17635 case OMPC_firstprivate:
17636 case OMPC_lastprivate:
17638 case OMPC_reduction:
17639 case OMPC_task_reduction:
17640 case OMPC_in_reduction:
17644 case OMPC_copyprivate:
17648 case OMPC_mergeable:
17649 case OMPC_threadprivate:
17650 case OMPC_groupprivate:
17651 case OMPC_allocate:
17668 case OMPC_num_teams:
17669 case OMPC_thread_limit:
17670 case OMPC_priority:
17671 case OMPC_grainsize:
17673 case OMPC_num_tasks:
17675 case OMPC_dist_schedule:
17677 case OMPC_defaultmap:
17682 case OMPC_use_device_ptr:
17683 case OMPC_use_device_addr:
17684 case OMPC_is_device_ptr:
17685 case OMPC_has_device_addr:
17686 case OMPC_unified_address:
17687 case OMPC_unified_shared_memory:
17688 case OMPC_reverse_offload:
17689 case OMPC_dynamic_allocators:
17690 case OMPC_self_maps:
17691 case OMPC_device_type:
17693 case OMPC_nontemporal:
17695 case OMPC_novariants:
17696 case OMPC_nocontext:
17698 case OMPC_inclusive:
17699 case OMPC_exclusive:
17700 case OMPC_uses_allocators:
17701 case OMPC_affinity:
17705 llvm_unreachable(
"Clause is not allowed.");
17714 if (M == OMP_DEFAULT_unknown) {
17715 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17717 unsigned(OMP_DEFAULT_unknown))
17722 Diag(VCKindLoc, diag::err_omp_default_vc)
17727 bool IsTargetDefault =
17734 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17737 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17743 case OMP_DEFAULT_none:
17744 if (IsTargetDefault)
17745 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17747 DSAStack->setDefaultDSANone(MLoc);
17749 case OMP_DEFAULT_firstprivate:
17750 if (IsTargetDefault)
17751 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17753 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17755 case OMP_DEFAULT_private:
17756 if (IsTargetDefault)
17757 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17759 DSAStack->setDefaultDSAPrivate(MLoc);
17761 case OMP_DEFAULT_shared:
17762 assert(!IsTargetDefault &&
"DSA shared invalid with target directive");
17763 DSAStack->setDefaultDSAShared(MLoc);
17766 llvm_unreachable(
"unexpected DSA in OpenMP default clause");
17770 case OMPC_DEFAULT_VC_aggregate:
17771 if (IsTargetDefault)
17772 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17774 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17776 case OMPC_DEFAULT_VC_pointer:
17777 if (IsTargetDefault)
17778 DefMapKind = OMPC_DEFAULTMAP_pointer;
17780 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17782 case OMPC_DEFAULT_VC_scalar:
17783 if (IsTargetDefault)
17784 DefMapKind = OMPC_DEFAULTMAP_scalar;
17786 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17788 case OMPC_DEFAULT_VC_all:
17789 if (IsTargetDefault)
17790 DefMapKind = OMPC_DEFAULTMAP_all;
17792 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17795 llvm_unreachable(
"unexpected variable category in OpenMP default clause");
17804 if (IsTargetDefault) {
17805 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17806 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17807 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17808 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17810 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17815 SetDefaultClauseAttrs(M, VCKind);
17817 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17826 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17829 << getOpenMPClauseName(OMPC_threadset);
17846 return new (Ctx) OMPTransparentClause(ER.
get(), HelperValStmt, CaptureRegion,
17847 StartLoc, LParenLoc, EndLoc);
17854 Stmt *HelperValStmt =
nullptr;
17858 if (CaptureRegion != OMPD_unknown &&
17859 !
SemaRef.CurContext->isDependentContext()) {
17860 Expr *ValExpr =
SemaRef.MakeFullExpr(ImpexTypeArg).get();
17861 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17862 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17865 if (!ImpexTypeArg) {
17867 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17868 StartLoc, LParenLoc, EndLoc);
17879 SemaRef.Diag(StartLoc, diag::err_omp_implied_type_not_found)
17884 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17885 StartLoc, LParenLoc, EndLoc);
17890 HelperValStmt, CaptureRegion, StartLoc,
17891 LParenLoc, EndLoc);
17896 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(StartLoc,
17898 if (std::optional<llvm::APSInt>
Result =
17899 Value.get()->getIntegerConstantExpr(
SemaRef.Context)) {
17900 if (
Result->isNegative() ||
17903 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_value);
17906 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17907 StartLoc, LParenLoc, EndLoc);
17914 ImpexTypeArg, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17922 if (Kind == OMP_PROC_BIND_unknown) {
17923 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17925 unsigned(OMP_PROC_BIND_master),
17928 ? OMP_PROC_BIND_primary
17929 : OMP_PROC_BIND_spread) +
17934 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
17935 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17937 unsigned(OMP_PROC_BIND_master),
17939 unsigned(OMP_PROC_BIND_spread) + 1)
17942 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17949 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17951 OMPC_atomic_default_mem_order, 0,
17956 return new (
getASTContext()) OMPAtomicDefaultMemOrderClause(
17957 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17966 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17973 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17982 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17989 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17996 assert(ME &&
"NULL expr in Message clause");
18005 Stmt *HelperValStmt =
nullptr;
18011 DKind == OMPD_unknown ? OMPD_unknown
18014 if (CaptureRegion != OMPD_unknown &&
18015 !
SemaRef.CurContext->isDependentContext()) {
18016 ME =
SemaRef.MakeFullExpr(ME).get();
18017 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18018 ME = tryBuildCapture(
SemaRef, ME, Captures).get();
18023 ME =
SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
18026 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18033 if (Kind != OMPC_ORDER_concurrent ||
18038 "OMPC_ORDER_unknown not greater than 0");
18040 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18049 Diag(MLoc, diag::err_omp_unexpected_clause_value)
18055 DSAStack->setRegionHasOrderConcurrent(
true);
18058 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
18059 DSAStack->getCurScope()->setFlags(existingFlags |
18064 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
18073 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
18075 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
18076 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
18078 Except.push_back(OMPC_DEPEND_inoutset);
18079 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
18085 return OMPUpdateClause::Create(
getASTContext(), StartLoc, LParenLoc,
18086 KindKwLoc, Kind, EndLoc);
18095 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
18105 QualType SizeTy = SizeExpr->getType();
18134 if (!SizeExpr->isInstantiationDependent() && !IsValid)
18135 SizeExpr =
nullptr;
18139 SanitizedSizeExprs);
18146 std::optional<unsigned> FillIdx,
18148 unsigned FillCount) {
18155 for (
unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
18156 Expr *&CountExpr = SanitizedCountExprs[I];
18157 if (FillIdx && I == *FillIdx)
18163 CountExpr, OMPC_counts,
false);
18165 CountExpr =
nullptr;
18167 CountExpr = Verified.
get();
18170 if (FillCount != 1) {
18171 Diag(FillCount == 0 ? StartLoc : FillLoc,
18172 diag::err_omp_split_counts_not_one_omp_fill);
18176 SanitizedCountExprs, FillIdx, FillLoc);
18183 size_t NumLoops = PermExprs.size();
18185 llvm::append_range(SanitizedPermExprs, PermExprs);
18187 for (
Expr *&PermExpr : SanitizedPermExprs) {
18190 if (!PermExpr || PermExpr->isInstantiationDependent())
18193 llvm::APSInt PermVal;
18196 bool IsValid = PermEvalExpr.
isUsable();
18198 PermExpr = PermEvalExpr.
get();
18200 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
18204 diag::err_omp_interchange_permutation_value_range)
18205 << NumLoops << ExprRange;
18209 if (!PermExpr->isInstantiationDependent() && !IsValid)
18210 PermExpr =
nullptr;
18214 EndLoc, SanitizedPermExprs);
18230 FactorExpr, OMPC_partial,
true);
18233 FactorExpr = FactorResult.
get();
18262 FirstLoc, CountLoc, EndLoc,
First, Count);
18273 LParenLoc, EndLoc);
18283 case OMPC_schedule: {
18284 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
18285 assert(Argument.size() == NumberOfElements &&
18286 ArgumentLoc.size() == NumberOfElements);
18291 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
18292 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
18296 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18298 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
18301 case OMPC_dist_schedule:
18304 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
18307 enum { DefaultModifier, DefaultVarCategory };
18309 static_cast<llvm::omp::DefaultKind
>(Argument[DefaultModifier]),
18310 ArgumentLoc[DefaultModifier],
18312 Argument[DefaultVarCategory]),
18313 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
18315 case OMPC_defaultmap:
18316 enum { Modifier, DefaultmapKind };
18320 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
18324 enum { OrderModifier, OrderKind };
18328 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
18331 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18334 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18336 case OMPC_grainsize:
18337 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18338 "Modifier for grainsize clause and its location are expected.");
18341 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18343 case OMPC_num_tasks:
18344 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18345 "Modifier for num_tasks clause and its location are expected.");
18348 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18350 case OMPC_dyn_groupprivate: {
18351 enum { Modifier1, Modifier2, NumberOfElements };
18352 assert(Argument.size() == NumberOfElements &&
18353 ArgumentLoc.size() == NumberOfElements &&
18354 "Modifiers for dyn_groupprivate clause and their locations are "
18359 Argument[Modifier2]),
18360 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
18361 ArgumentLoc[Modifier2], EndLoc);
18364 case OMPC_num_threads:
18365 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18366 "Modifier for num_threads clause and its location are expected.");
18369 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18375 case OMPC_allocator:
18376 case OMPC_collapse:
18377 case OMPC_proc_bind:
18379 case OMPC_firstprivate:
18380 case OMPC_lastprivate:
18382 case OMPC_reduction:
18383 case OMPC_task_reduction:
18384 case OMPC_in_reduction:
18388 case OMPC_copyprivate:
18392 case OMPC_mergeable:
18393 case OMPC_threadprivate:
18394 case OMPC_groupprivate:
18395 case OMPC_allocate:
18412 case OMPC_num_teams:
18413 case OMPC_thread_limit:
18414 case OMPC_priority:
18421 case OMPC_use_device_ptr:
18422 case OMPC_use_device_addr:
18423 case OMPC_is_device_ptr:
18424 case OMPC_has_device_addr:
18425 case OMPC_unified_address:
18426 case OMPC_unified_shared_memory:
18427 case OMPC_reverse_offload:
18428 case OMPC_dynamic_allocators:
18429 case OMPC_atomic_default_mem_order:
18430 case OMPC_self_maps:
18431 case OMPC_device_type:
18433 case OMPC_nontemporal:
18435 case OMPC_severity:
18438 case OMPC_novariants:
18439 case OMPC_nocontext:
18441 case OMPC_inclusive:
18442 case OMPC_exclusive:
18443 case OMPC_uses_allocators:
18444 case OMPC_affinity:
18448 llvm_unreachable(
"Clause is not allowed.");
18459 Excluded.push_back(M2);
18460 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18461 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
18462 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18463 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18464 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
18487 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18488 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18489 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18490 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18491 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
18497 std::string Values;
18507 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18516 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18517 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18518 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18519 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18520 diag::err_omp_schedule_nonmonotonic_static);
18523 Expr *ValExpr = ChunkSize;
18524 Stmt *HelperValStmt =
nullptr;
18535 ValExpr = Val.
get();
18540 if (std::optional<llvm::APSInt>
Result =
18542 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
18543 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18548 DSAStack->getCurrentDirective(), OMPC_schedule,
18550 !
SemaRef.CurContext->isDependentContext()) {
18551 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18552 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18553 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18560 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18561 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18580 case OMPC_mergeable:
18628 case OMPC_unified_address:
18631 case OMPC_unified_shared_memory:
18634 case OMPC_reverse_offload:
18637 case OMPC_dynamic_allocators:
18640 case OMPC_self_maps:
18654 case OMPC_ompx_bare:
18659 case OMPC_num_threads:
18663 case OMPC_allocator:
18664 case OMPC_collapse:
18665 case OMPC_schedule:
18667 case OMPC_firstprivate:
18668 case OMPC_lastprivate:
18670 case OMPC_reduction:
18671 case OMPC_task_reduction:
18672 case OMPC_in_reduction:
18676 case OMPC_copyprivate:
18678 case OMPC_proc_bind:
18679 case OMPC_threadprivate:
18680 case OMPC_groupprivate:
18681 case OMPC_allocate:
18687 case OMPC_num_teams:
18688 case OMPC_thread_limit:
18689 case OMPC_priority:
18690 case OMPC_grainsize:
18691 case OMPC_num_tasks:
18693 case OMPC_dist_schedule:
18694 case OMPC_defaultmap:
18699 case OMPC_use_device_ptr:
18700 case OMPC_use_device_addr:
18701 case OMPC_is_device_ptr:
18702 case OMPC_has_device_addr:
18703 case OMPC_atomic_default_mem_order:
18704 case OMPC_device_type:
18706 case OMPC_nontemporal:
18709 case OMPC_severity:
18711 case OMPC_novariants:
18712 case OMPC_nocontext:
18714 case OMPC_inclusive:
18715 case OMPC_exclusive:
18716 case OMPC_uses_allocators:
18717 case OMPC_affinity:
18719 case OMPC_ompx_dyn_cgroup_mem:
18720 case OMPC_dyn_groupprivate:
18722 llvm_unreachable(
"Clause is not allowed.");
18734 !
Condition->isInstantiationDependent() &&
18735 !
Condition->containsUnexpandedParameterPack()) {
18740 ValExpr = Val.
get();
18745 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18751 return new (
getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18756 return new (
getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18761 return new (
getASTContext()) OMPReadClause(StartLoc, EndLoc);
18766 return new (
getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18771 return OMPUpdateClause::Create(
getASTContext(), StartLoc, EndLoc);
18776 return new (
getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18781 return new (
getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18786 return new (
getASTContext()) OMPFailClause(StartLoc, EndLoc);
18796 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18800 OMPFailClause(
Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18805 return new (
getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18810 return new (
getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18815 return new (
getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18820 return new (
getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18825 return new (
getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18830 return new (
getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18850 return new (
getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18856 return new (
getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18861 return new (
getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18867 return new (
getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18872 return new (
getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18882 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18884 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
18885 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18886 <<
Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18899 bool HasInitClause =
false;
18900 bool IsTargetSync =
false;
18904 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
18905 HasInitClause =
true;
18906 if (InitClause->getIsTargetSync())
18907 IsTargetSync =
true;
18908 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
18912 if (DependClause && HasInitClause && !IsTargetSync) {
18913 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18927 if (ClauseKind == OMPC_init) {
18930 }
else if (ClauseKind == OMPC_use) {
18933 }
else if (ClauseKind == OMPC_destroy) {
18939 if (!InteropVars.insert(
DeclResult.first).second) {
18940 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18956 Expr *RefExpr = InteropVarExpr;
18971 bool HasError =
false;
18977 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
18978 InteropType =
QualType(TD->getTypeForDecl(), 0);
18987 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
18988 <<
"omp_interop_t";
18994 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
19000 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
19002 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
19023 assert(InteropInfo.
HasPreferAttrs &&
"null Fr requires OMP 6.0 syntax");
19037 const auto *SL = dyn_cast<StringLiteral>(A);
19042 if (!SL->getString().starts_with(
"ompx_")) {
19043 Diag(A->
getExprLoc(), diag::err_omp_interop_attr_missing_ompx_prefix)
19044 << SL->getString();
19047 if (SL->getString().contains(
',')) {
19048 Diag(A->
getExprLoc(), diag::err_omp_interop_attr_contains_comma)
19049 << SL->getString();
19056 StartLoc, LParenLoc, VarLoc, EndLoc);
19069 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19078 DSAStack->getCurrentDirective() == OMPD_depobj) {
19080 Diag(StartLoc, diag::err_omp_expected_clause_argument)
19082 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
19098 Stmt *HelperValStmt =
nullptr;
19101 !
Condition->isInstantiationDependent() &&
19102 !
Condition->containsUnexpandedParameterPack()) {
19107 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
19112 if (CaptureRegion != OMPD_unknown &&
19113 !
SemaRef.CurContext->isDependentContext()) {
19114 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
19115 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19116 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
19122 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19130 Stmt *HelperValStmt =
nullptr;
19133 !
Condition->isInstantiationDependent() &&
19134 !
Condition->containsUnexpandedParameterPack()) {
19139 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
19144 if (CaptureRegion != OMPD_unknown &&
19145 !
SemaRef.CurContext->isDependentContext()) {
19146 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
19147 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19148 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
19154 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19161 Expr *ValExpr = ThreadID;
19162 Stmt *HelperValStmt =
nullptr;
19167 if (CaptureRegion != OMPD_unknown &&
19168 !
SemaRef.CurContext->isDependentContext()) {
19169 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
19170 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19171 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
19176 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19187 int ExtraModifier =
Data.ExtraModifier;
19188 int OriginalSharingModifier =
Data.OriginalSharingModifier;
19189 Expr *ExtraModifierExpr =
Data.ExtraModifierExpr;
19196 case OMPC_firstprivate:
19199 case OMPC_lastprivate:
19201 "Unexpected lastprivate modifier.");
19204 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
19209 case OMPC_reduction:
19211 "Unexpected lastprivate modifier.");
19215 ExtraModifier, OriginalSharingModifier),
19216 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
19217 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
19219 case OMPC_task_reduction:
19221 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19222 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
19224 case OMPC_in_reduction:
19226 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19227 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
19231 "Unexpected linear modifier.");
19233 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
19235 ColonLoc,
Data.StepModifierLoc, EndLoc);
19239 LParenLoc, ColonLoc, EndLoc);
19244 case OMPC_copyprivate:
19252 "Unexpected depend modifier.");
19255 ColonLoc,
Data.OmpAllMemoryLoc},
19256 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
19260 "Unexpected map modifier.");
19262 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
19263 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
19265 ExtraModifierLoc, ColonLoc, VarList, Locs);
19269 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
19270 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
19275 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
19276 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
19279 case OMPC_use_device_ptr:
19280 assert(0 <=
Data.ExtraModifier &&
19282 "Unexpected use_device_ptr fallback modifier.");
19286 Data.ExtraModifierLoc);
19288 case OMPC_use_device_addr:
19291 case OMPC_is_device_ptr:
19294 case OMPC_has_device_addr:
19297 case OMPC_allocate: {
19301 if (!
Data.AllocClauseModifiers.empty()) {
19302 assert(
Data.AllocClauseModifiers.size() <= 2 &&
19303 "More allocate modifiers than expected");
19304 Modifier1 =
Data.AllocClauseModifiers[0];
19305 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
19306 if (
Data.AllocClauseModifiers.size() == 2) {
19307 Modifier2 =
Data.AllocClauseModifiers[1];
19308 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
19312 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
19313 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
19317 case OMPC_nontemporal:
19320 case OMPC_inclusive:
19323 case OMPC_exclusive:
19326 case OMPC_affinity:
19328 Data.DepModOrTailExpr, VarList);
19330 case OMPC_doacross:
19333 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
19335 case OMPC_num_teams:
19337 "Unexpected num_teams modifier.");
19340 ExtraModifierExpr, ExtraModifierLoc, StartLoc, LParenLoc, EndLoc);
19342 case OMPC_thread_limit:
19348 case OMPC_num_threads:
19352 case OMPC_allocator:
19353 case OMPC_collapse:
19355 case OMPC_proc_bind:
19356 case OMPC_schedule:
19360 case OMPC_mergeable:
19361 case OMPC_threadprivate:
19362 case OMPC_groupprivate:
19376 case OMPC_priority:
19377 case OMPC_grainsize:
19379 case OMPC_num_tasks:
19381 case OMPC_dist_schedule:
19382 case OMPC_defaultmap:
19385 case OMPC_unified_address:
19386 case OMPC_unified_shared_memory:
19387 case OMPC_reverse_offload:
19388 case OMPC_dynamic_allocators:
19389 case OMPC_atomic_default_mem_order:
19390 case OMPC_self_maps:
19391 case OMPC_device_type:
19395 case OMPC_severity:
19398 case OMPC_novariants:
19399 case OMPC_nocontext:
19401 case OMPC_uses_allocators:
19405 llvm_unreachable(
"Clause is not allowed.");
19418 Res =
SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.
get());
19423 Res =
SemaRef.DefaultLvalueConversion(Res.
get());
19437 bool IsImplicitClause =
19439 for (
Expr *RefExpr : VarList) {
19440 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
19443 Expr *SimpleRefExpr = RefExpr;
19447 Vars.push_back(RefExpr);
19448 PrivateCopies.push_back(
nullptr);
19455 auto *VD = dyn_cast<VarDecl>(D);
19461 diag::err_omp_private_incomplete_type))
19463 Type =
Type.getNonReferenceType();
19483 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19484 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19485 Diag(ELoc, diag::err_omp_wrong_dsa)
19496 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19498 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19499 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19502 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19517 CurrDir == OMPD_target) {
19519 if (
DSAStack->checkMappableExprComponentListsForDecl(
19523 ConflictKind = WhereFoundClauseKind;
19526 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19529 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19549 SemaRef.ActOnUninitializedDecl(VDPrivate);
19556 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19557 auto *FD = dyn_cast<FieldDecl>(D);
19561 RefExpr->getExprLoc());
19565 if (!IsImplicitClause)
19566 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19567 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19568 ? RefExpr->IgnoreParens()
19570 PrivateCopies.push_back(VDPrivateRefExpr);
19576 return OMPPrivateClause::Create(
getASTContext(), StartLoc, LParenLoc, EndLoc,
19577 Vars, PrivateCopies);
19588 bool IsImplicitClause =
19593 for (
Expr *RefExpr : VarList) {
19594 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
19597 Expr *SimpleRefExpr = RefExpr;
19601 Vars.push_back(RefExpr);
19602 PrivateCopies.push_back(
nullptr);
19603 Inits.push_back(
nullptr);
19609 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19611 auto *VD = dyn_cast<VarDecl>(D);
19617 diag::err_omp_firstprivate_incomplete_type))
19619 Type =
Type.getNonReferenceType();
19629 DSAStackTy::DSAVarData TopDVar;
19630 if (!IsImplicitClause) {
19631 DSAStackTy::DSAVarData DVar =
19643 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19645 DVar.CKind != OMPC_lastprivate) &&
19647 Diag(ELoc, diag::err_omp_wrong_dsa)
19665 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19666 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19667 Diag(ELoc, diag::err_omp_wrong_dsa)
19693 DVar =
DSAStack->getImplicitDSA(D,
true);
19694 if (DVar.CKind != OMPC_shared &&
19697 DVar.DKind == OMPD_unknown)) {
19698 Diag(ELoc, diag::err_omp_required_access)
19720 return C == OMPC_reduction && !AppliedToPointee;
19728 if (DVar.CKind == OMPC_reduction &&
19732 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19733 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19749 CurrDir == OMPD_target) {
19751 if (
DSAStack->checkMappableExprComponentListsForDecl(
19756 ConflictKind = WhereFoundClauseKind;
19759 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19762 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19773 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19775 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
19777 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19780 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19795 Expr *VDInitRefExpr =
nullptr;
19805 ElemType,
".firstprivate.temp");
19820 ".firstprivate.temp");
19822 RefExpr->getExprLoc());
19823 SemaRef.AddInitializerToDecl(
19824 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19828 if (IsImplicitClause) {
19829 Diag(RefExpr->getExprLoc(),
19830 diag::note_omp_task_predetermined_firstprivate_here);
19834 SemaRef.CurContext->addDecl(VDPrivate);
19837 RefExpr->getExprLoc());
19839 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
19840 if (TopDVar.CKind == OMPC_lastprivate) {
19841 Ref = TopDVar.PrivateCopy;
19843 auto *FD = dyn_cast<FieldDecl>(D);
19848 RefExpr->getExprLoc());
19852 ExprCaptures.push_back(Ref->
getDecl());
19855 if (!IsImplicitClause)
19856 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19857 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
19858 ? RefExpr->IgnoreParens()
19860 PrivateCopies.push_back(VDPrivateRefExpr);
19861 Inits.push_back(VDInitRefExpr);
19867 return OMPFirstprivateClause::Create(
19877 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
19878 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19891 for (
Expr *RefExpr : VarList) {
19892 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
19895 Expr *SimpleRefExpr = RefExpr;
19899 Vars.push_back(RefExpr);
19900 SrcExprs.push_back(
nullptr);
19901 DstExprs.push_back(
nullptr);
19902 AssignmentOps.push_back(
nullptr);
19909 auto *VD = dyn_cast<VarDecl>(D);
19915 diag::err_omp_lastprivate_incomplete_type))
19917 Type =
Type.getNonReferenceType();
19934 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19935 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19938 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19952 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
19953 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19955 DVar.CKind != OMPC_firstprivate) &&
19956 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
19957 Diag(ELoc, diag::err_omp_wrong_dsa)
19970 DSAStackTy::DSAVarData TopDVar = DVar;
19974 DVar =
DSAStack->getImplicitDSA(D,
true);
19975 if (DVar.CKind != OMPC_shared) {
19976 Diag(ELoc, diag::err_omp_required_access)
19994 Type.getUnqualifiedType(),
".lastprivate.src",
20005 PseudoDstExpr, PseudoSrcExpr);
20008 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
20014 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
20015 if (TopDVar.CKind == OMPC_firstprivate) {
20016 Ref = TopDVar.PrivateCopy;
20020 ExprCaptures.push_back(Ref->
getDecl());
20022 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
20030 SimpleRefExpr, RefRes.
get());
20033 ExprPostUpdates.push_back(
20034 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
20037 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
20038 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
20039 ? RefExpr->IgnoreParens()
20041 SrcExprs.push_back(PseudoSrcExpr);
20042 DstExprs.push_back(PseudoDstExpr);
20043 AssignmentOps.push_back(AssignmentOp.
get());
20049 return OMPLastprivateClause::Create(
20050 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
20051 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
20061 for (
Expr *RefExpr : VarList) {
20062 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
20065 Expr *SimpleRefExpr = RefExpr;
20069 Vars.push_back(RefExpr);
20075 auto *VD = dyn_cast<VarDecl>(D);
20083 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
20084 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
20086 Diag(ELoc, diag::err_omp_wrong_dsa)
20095 !
SemaRef.CurContext->isDependentContext())
20097 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
20098 Vars.push_back((VD || !Ref ||
SemaRef.CurContext->isDependentContext())
20099 ? RefExpr->IgnoreParens()
20106 return OMPSharedClause::Create(
getASTContext(), StartLoc, LParenLoc, EndLoc,
20111class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
20116 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
20117 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
20118 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
20120 if (DVar.CKind != OMPC_unknown)
20122 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
20129 return DVarPrivate.CKind != OMPC_unknown;
20133 bool VisitStmt(Stmt *S) {
20134 for (Stmt *Child : S->
children()) {
20135 if (Child && Visit(Child))
20140 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
20147class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
20148 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
20149 ValueDecl *
Field =
nullptr;
20150 DeclRefExpr *CapturedExpr =
nullptr;
20153 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
20154 : BaseTransform(SemaRef),
Field(FieldDecl), CapturedExpr(
nullptr) {}
20156 ExprResult TransformMemberExpr(MemberExpr *E) {
20159 CapturedExpr =
buildCapture(SemaRef, Field, E,
false);
20160 return CapturedExpr;
20162 return BaseTransform::TransformMemberExpr(E);
20164 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
20168template <
typename T,
typename U>
20171 for (
U &
Set : Lookups) {
20172 for (
auto *D :
Set) {
20183 for (
auto *RD : D->
redecls()) {
20206 AssociatedClasses);
20219 for (
auto *NS : AssociatedNamespaces) {
20232 for (
auto *D : R) {
20233 auto *Underlying = D;
20234 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
20235 Underlying = USD->getTargetDecl();
20245 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
20246 Underlying = USD->getTargetDecl();
20248 Lookups.emplace_back();
20249 Lookups.back().addDecl(Underlying);
20273 Lookups.emplace_back();
20274 Lookups.back().append(Lookup.
begin(), Lookup.
end());
20277 }
else if (
auto *ULE =
20278 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
20280 Decl *PrevD =
nullptr;
20284 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
20285 Lookups.back().addDecl(DRD);
20293 return !D->isInvalidDecl() &&
20294 (D->getType()->isDependentType() ||
20295 D->getType()->isInstantiationDependentType() ||
20296 D->getType()->containsUnexpandedParameterPack());
20309 true, ResSet.
begin(), ResSet.
end(),
false,
20332 if (IsComplete || RD->isBeingDefined()) {
20335 if (Lookup.
empty()) {
20336 Lookups.emplace_back();
20337 Lookups.back().append(Lookup.
begin(), Lookup.
end());
20379 if (ReductionIdScopeSpec.
isSet()) {
20380 SemaRef.
Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
20389struct ReductionData {
20391 SmallVector<Expr *, 8> Vars;
20395 SmallVector<Expr *, 8> LHSs;
20397 SmallVector<Expr *, 8> RHSs;
20399 SmallVector<Expr *, 8> ReductionOps;
20401 SmallVector<Expr *, 8> InscanCopyOps;
20403 SmallVector<Expr *, 8> InscanCopyArrayTemps;
20405 SmallVector<Expr *, 8> InscanCopyArrayElems;
20408 SmallVector<Expr *, 8> TaskgroupDescriptors;
20410 SmallVector<Decl *, 4> ExprCaptures;
20412 SmallVector<Expr *, 4> ExprPostUpdates;
20414 unsigned RedModifier = 0;
20416 unsigned OrigSharingModifier = 0;
20418 SmallVector<bool, 8> IsPrivateVarReduction;
20419 ReductionData() =
delete;
20421 ReductionData(
unsigned Size,
unsigned Modifier = 0,
unsigned OrgModifier = 0)
20422 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
20423 Vars.reserve(Size);
20425 LHSs.reserve(Size);
20426 RHSs.reserve(Size);
20427 ReductionOps.reserve(Size);
20428 IsPrivateVarReduction.reserve(Size);
20429 if (RedModifier == OMPC_REDUCTION_inscan) {
20430 InscanCopyOps.reserve(Size);
20431 InscanCopyArrayTemps.reserve(Size);
20432 InscanCopyArrayElems.reserve(Size);
20434 TaskgroupDescriptors.reserve(Size);
20435 ExprCaptures.reserve(Size);
20436 ExprPostUpdates.reserve(Size);
20440 void push(Expr *Item, Expr *ReductionOp) {
20441 Vars.emplace_back(Item);
20443 LHSs.emplace_back(
nullptr);
20444 RHSs.emplace_back(
nullptr);
20445 ReductionOps.emplace_back(ReductionOp);
20446 IsPrivateVarReduction.emplace_back(
false);
20447 TaskgroupDescriptors.emplace_back(
nullptr);
20448 if (RedModifier == OMPC_REDUCTION_inscan) {
20449 InscanCopyOps.push_back(
nullptr);
20450 InscanCopyArrayTemps.push_back(
nullptr);
20451 InscanCopyArrayElems.push_back(
nullptr);
20455 void push(Expr *Item, Expr *
Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
20456 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
20457 Expr *CopyArrayElem,
bool IsPrivate) {
20458 Vars.emplace_back(Item);
20460 LHSs.emplace_back(LHS);
20461 RHSs.emplace_back(RHS);
20462 ReductionOps.emplace_back(ReductionOp);
20463 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
20464 if (RedModifier == OMPC_REDUCTION_inscan) {
20465 InscanCopyOps.push_back(CopyOp);
20466 InscanCopyArrayTemps.push_back(CopyArrayTemp);
20467 InscanCopyArrayElems.push_back(CopyArrayElem);
20469 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
20470 CopyArrayElem ==
nullptr &&
20471 "Copy operation must be used for inscan reductions only.");
20473 IsPrivateVarReduction.emplace_back(IsPrivate);
20482 if (Length ==
nullptr) {
20489 SingleElement =
true;
20490 ArraySizes.push_back(llvm::APSInt::get(1));
20493 if (!Length->EvaluateAsInt(
Result, Context))
20496 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
20497 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20498 ArraySizes.push_back(ConstantLengthValue);
20506 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
20507 Length = TempOASE->getLength();
20508 if (Length ==
nullptr) {
20515 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20516 ArraySizes.push_back(ConstantOne);
20519 if (!Length->EvaluateAsInt(
Result, Context))
20522 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
20523 if (ConstantLengthValue.getSExtValue() != 1)
20526 ArraySizes.push_back(ConstantLengthValue);
20528 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20532 if (!SingleElement) {
20533 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
20535 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20536 ArraySizes.push_back(ConstantOne);
20537 Base = TempASE->getBase()->IgnoreParenImpCasts();
20549 return BO_AddAssign;
20551 return BO_MulAssign;
20553 return BO_AndAssign;
20555 return BO_OrAssign;
20557 return BO_XorAssign;
20613 case OO_Array_Delete:
20622 case OO_GreaterEqual:
20624 case OO_MinusEqual:
20626 case OO_SlashEqual:
20627 case OO_PercentEqual:
20628 case OO_CaretEqual:
20632 case OO_GreaterGreater:
20633 case OO_LessLessEqual:
20634 case OO_GreaterGreaterEqual:
20635 case OO_EqualEqual:
20636 case OO_ExclaimEqual:
20639 case OO_MinusMinus:
20645 case OO_Conditional:
20648 llvm_unreachable(
"Unexpected reduction identifier");
20651 if (II->isStr(
"max"))
20653 else if (II->isStr(
"min"))
20661 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
20662 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20665 if (ReductionIdScopeSpec.
isValid())
20671 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20672 bool FirstIter =
true;
20673 for (
Expr *RefExpr : VarList) {
20674 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
20682 if (!FirstIter && IR != ER)
20687 bool IsPrivate =
false;
20688 Expr *SimpleRefExpr = RefExpr;
20697 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20698 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20699 Expr *ReductionOp =
nullptr;
20701 (DeclareReductionRef.
isUnset() ||
20703 ReductionOp = DeclareReductionRef.
get();
20705 RD.push(RefExpr, ReductionOp);
20711 Expr *TaskgroupDescriptor =
nullptr;
20713 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20714 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20716 Type = ASE->getType().getNonReferenceType();
20720 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20721 Type = ATy->getElementType();
20724 Type =
Type.getNonReferenceType();
20728 auto *VD = dyn_cast<VarDecl>(D);
20734 diag::err_omp_reduction_incomplete_type))
20740 false, ASE || OASE))
20747 if (!ASE && !OASE) {
20749 VarDecl *VDDef = VD->getDefinition();
20751 DSARefChecker Check(Stack);
20752 if (Check.Visit(VDDef->
getInit())) {
20753 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20772 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20773 if (DVar.CKind == OMPC_reduction) {
20774 S.
Diag(ELoc, diag::err_omp_once_referenced)
20780 if (DVar.CKind != OMPC_unknown) {
20781 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20797 DVar = Stack->getImplicitDSA(D,
true);
20798 if (DVar.CKind != OMPC_shared) {
20799 S.
Diag(ELoc, diag::err_omp_required_access)
20813 DVar = Stack->getImplicitDSA(D,
true);
20815 IsPrivate = DVar.CKind != OMPC_shared;
20816 bool IsOrphaned =
false;
20818 IsOrphaned = ParentDir == OMPD_unknown;
20820 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20826 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
20827 if (DVar.CKind == OMPC_threadprivate) {
20828 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
20840 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20841 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
20845 (DeclareReductionRef.
isUnset() ||
20847 RD.push(RefExpr, DeclareReductionRef.
get());
20849 if (RD.RedModifier == OMPC_REDUCTION_inscan)
20850 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction,
nullptr,
20851 RD.RedModifier, ASE || OASE);
20854 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
20858 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20859 <<
Type << ReductionIdRange;
20862 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20863 <<
Type << ReductionIdRange;
20875 if (DeclareReductionRef.
isUnset()) {
20876 if ((BOK == BO_GT || BOK == BO_LT) &&
20879 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20882 if (!ASE && !OASE) {
20883 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20886 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20891 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20893 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20895 if (!ASE && !OASE) {
20896 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20899 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20906 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
20915 bool ConstantLengthOASE =
false;
20917 bool SingleElement;
20920 Context, OASE, SingleElement, ArraySizes);
20923 if (ConstantLengthOASE && !SingleElement) {
20924 for (llvm::APSInt &Size : ArraySizes)
20925 PrivateTy = Context.getConstantArrayType(PrivateTy, Size,
nullptr,
20931 if ((OASE && !ConstantLengthOASE) ||
20934 if (!Context.getTargetInfo().isVLASupported()) {
20936 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20937 S.
Diag(ELoc, diag::note_vla_unsupported);
20940 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20941 S.
targetDiag(ELoc, diag::note_vla_unsupported);
20949 PrivateTy = Context.getVariableArrayType(
20954 }
else if (!ASE && !OASE &&
20967 if (DeclareReductionRef.
isUsable()) {
20970 if (DRD->getInitializer()) {
21024 Type = ComplexTy->getElementType();
21026 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
21027 Context.getFloatTypeSemantics(
Type));
21031 uint64_t Size = Context.getTypeSize(
Type);
21032 QualType IntTy = Context.getIntTypeForBitwidth(Size, 0);
21033 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
21052 uint64_t Size = Context.getTypeSize(
Type);
21054 Context.getIntTypeForBitwidth(Size, IsSigned);
21055 llvm::APInt InitValue =
21056 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
21057 : llvm::APInt::getMinValue(Size)
21058 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
21059 : llvm::APInt::getMaxValue(Size);
21064 ELoc, Context.getTrivialTypeSourceInfo(
Type, ELoc), ELoc,
Init);
21070 llvm::APFloat InitValue = llvm::APFloat::getLargest(
21071 Context.getFloatTypeSemantics(
Type), BOK != BO_LT);
21101 llvm_unreachable(
"Unexpected reduction operation");
21110 }
else if (!
Init) {
21120 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
21121 <<
Type << ReductionIdRange;
21122 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21125 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21131 if (DeclareReductionRef.
isUsable()) {
21133 QualType PtrRedTy = Context.getPointerType(RedTy);
21136 if (!BasePath.empty()) {
21140 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
21143 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
21147 QualType Params[] = {PtrRedTy, PtrRedTy};
21148 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
21162 CombBOK, LHSDRE, RHSDRE);
21169 if (BOK != BO_LT && BOK != BO_GT) {
21172 BO_Assign, LHSDRE, ReductionOp.
get());
21174 auto *ConditionalOp =
new (Context)
21179 BO_Assign, LHSDRE, ConditionalOp);
21192 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
21193 if (ClauseKind == OMPC_reduction &&
21194 RD.RedModifier == OMPC_REDUCTION_inscan) {
21196 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
21206 if (Stack->getCurrentDirective() == OMPD_simd ||
21244 if (ClauseKind == OMPC_in_reduction) {
21247 const Expr *ParentReductionOp =
nullptr;
21248 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
21249 DSAStackTy::DSAVarData ParentBOKDSA =
21250 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
21252 DSAStackTy::DSAVarData ParentReductionOpDSA =
21253 Stack->getTopMostTaskgroupReductionData(
21254 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
21255 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
21256 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
21257 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
21258 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
21259 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
21260 bool EmitError =
true;
21261 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
21262 llvm::FoldingSetNodeID RedId, ParentRedId;
21263 ParentReductionOp->
Profile(ParentRedId, Context,
true);
21264 DeclareReductionRef.
get()->
Profile(RedId, Context,
21266 EmitError = RedId != ParentRedId;
21270 diag::err_omp_reduction_identifier_mismatch)
21271 << ReductionIdRange << RefExpr->getSourceRange();
21273 diag::note_omp_previous_reduction_identifier)
21275 << (IsParentBOK ? ParentBOKDSA.RefExpr
21276 : ParentReductionOpDSA.RefExpr)
21277 ->getSourceRange();
21281 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
21288 TransformExprToCaptures RebuildToCapture(S, D);
21290 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
21291 Ref = RebuildToCapture.getCapturedExpr();
21293 VarsExpr = Ref =
buildCapture(S, D, SimpleRefExpr,
false);
21296 RD.ExprCaptures.emplace_back(Ref->
getDecl());
21302 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
21307 Stack->getCurrentDirective() == OMPD_taskgroup) {
21308 S.
Diag(RefExpr->getExprLoc(),
21309 diag::err_omp_reduction_non_addressable_expression)
21310 << RefExpr->getSourceRange();
21313 RD.ExprPostUpdates.emplace_back(
21320 unsigned Modifier = RD.RedModifier;
21323 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
21324 Modifier = OMPC_REDUCTION_task;
21325 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
21327 if (Modifier == OMPC_REDUCTION_task &&
21328 (CurrDir == OMPD_taskgroup ||
21332 if (DeclareReductionRef.
isUsable())
21333 Stack->addTaskgroupReductionData(D, ReductionIdRange,
21334 DeclareReductionRef.
get());
21336 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
21338 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
21339 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
21340 TempArrayElem.
get(), IsPrivate);
21342 return RD.Vars.empty();
21358 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
21369 if (Modifier == OMPC_REDUCTION_inscan &&
21370 (
DSAStack->getCurrentDirective() != OMPD_for &&
21371 DSAStack->getCurrentDirective() != OMPD_for_simd &&
21372 DSAStack->getCurrentDirective() != OMPD_simd &&
21373 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
21374 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
21375 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
21378 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
21380 StartLoc, LParenLoc, ColonLoc, EndLoc,
21381 ReductionIdScopeSpec, ReductionId,
21382 UnresolvedReductions, RD))
21385 return OMPReductionClause::Create(
21386 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
21389 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
21390 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
21393 OriginalSharingModifier);
21401 ReductionData RD(VarList.size());
21403 VarList, StartLoc, LParenLoc, ColonLoc,
21404 EndLoc, ReductionIdScopeSpec, ReductionId,
21405 UnresolvedReductions, RD))
21408 return OMPTaskReductionClause::Create(
21409 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
21411 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
21421 ReductionData RD(VarList.size());
21423 StartLoc, LParenLoc, ColonLoc, EndLoc,
21424 ReductionIdScopeSpec, ReductionId,
21425 UnresolvedReductions, RD))
21428 return OMPInReductionClause::Create(
21429 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
21431 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
21440 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
21450 const auto *VD = dyn_cast_or_null<VarDecl>(D);
21453 diag::err_omp_linear_incomplete_type))
21455 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
21457 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
21461 Type =
Type.getNonReferenceType();
21468 if (!IsDeclareSimd &&
21473 Type =
Type.getUnqualifiedType().getCanonicalType();
21474 const auto *Ty =
Type.getTypePtrOrNull();
21475 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
21476 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
21477 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
21479 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21482 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21505 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
21507 LinKind = OMPC_LINEAR_val;
21508 for (
Expr *RefExpr : VarList) {
21509 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
21512 Expr *SimpleRefExpr = RefExpr;
21516 Vars.push_back(RefExpr);
21518 Inits.push_back(
nullptr);
21525 auto *VD = dyn_cast<VarDecl>(D);
21531 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
21532 if (DVar.RefExpr) {
21533 Diag(ELoc, diag::err_omp_wrong_dsa)
21542 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21554 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
21557 ExprCaptures.push_back(Ref->
getDecl());
21564 SimpleRefExpr, RefRes.
get());
21567 ExprPostUpdates.push_back(
21568 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
21572 if (LinKind == OMPC_LINEAR_uval)
21573 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21575 InitExpr = VD ? SimpleRefExpr : Ref;
21576 SemaRef.AddInitializerToDecl(
21577 Init,
SemaRef.DefaultLvalueConversion(InitExpr).get(),
21581 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
21582 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
21583 ? RefExpr->IgnoreParens()
21586 Inits.push_back(InitRef);
21592 Expr *StepExpr = Step;
21593 Expr *CalcStepExpr =
nullptr;
21601 StepExpr = Val.
get();
21609 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.
get(), StepExpr);
21611 SemaRef.ActOnFinishFullExpr(CalcStep.
get(),
false);
21615 if (std::optional<llvm::APSInt>
Result =
21617 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
21618 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21619 << Vars[0] << (Vars.size() > 1);
21623 CalcStepExpr = CalcStep.
get();
21627 return OMPLinearClause::Create(
getASTContext(), StartLoc, LParenLoc, LinKind,
21628 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21635 Expr *NumIterations,
Sema &SemaRef,
21636 Scope *S, DSAStackTy *Stack) {
21641 Expr *Step = Clause.getStep();
21642 Expr *CalcStep = Clause.getCalcStep();
21649 bool HasErrors =
false;
21650 auto CurInit = Clause.inits().begin();
21651 auto CurPrivate = Clause.privates().begin();
21653 for (
Expr *RefExpr : Clause.varlist()) {
21656 Expr *SimpleRefExpr = RefExpr;
21657 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21659 if (Res.second || !D) {
21661 Finals.push_back(
nullptr);
21665 auto &&Info = Stack->isLoopControlVariable(D);
21672 diag::err_omp_linear_distribute_var_non_loop_iteration);
21674 Finals.push_back(
nullptr);
21678 Expr *InitExpr = *CurInit;
21683 if (LinKind == OMPC_LINEAR_uval)
21688 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21695 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21706 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21709 Final = *CurPrivate;
21713 if (!
Update.isUsable() || !Final.isUsable()) {
21715 Finals.push_back(
nullptr);
21716 UsedExprs.push_back(
nullptr);
21720 Finals.push_back(Final.get());
21722 UsedExprs.push_back(SimpleRefExpr);
21727 if (
Expr *S = Clause.getStep())
21728 UsedExprs.push_back(S);
21730 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(),
nullptr);
21732 Clause.setFinals(Finals);
21733 Clause.setUsedExprs(UsedExprs);
21741 for (
Expr *RefExpr : VarList) {
21742 assert(RefExpr &&
"NULL expr in OpenMP aligned clause.");
21745 Expr *SimpleRefExpr = RefExpr;
21749 Vars.push_back(RefExpr);
21756 auto *VD = dyn_cast<VarDecl>(D);
21764 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21766 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21769 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21776 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21777 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21779 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21788 .DefaultFunctionArrayConversion(
21789 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21798 if (Alignment !=
nullptr) {
21803 Alignment = AlignResult.
get();
21809 ColonLoc, EndLoc, Vars, Alignment);
21820 for (
Expr *RefExpr : VarList) {
21821 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
21824 Vars.push_back(RefExpr);
21825 SrcExprs.push_back(
nullptr);
21826 DstExprs.push_back(
nullptr);
21827 AssignmentOps.push_back(
nullptr);
21836 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21838 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21839 << 0 << RefExpr->getSourceRange();
21843 Decl *D = DE->getDecl();
21849 Vars.push_back(DE);
21850 SrcExprs.push_back(
nullptr);
21851 DstExprs.push_back(
nullptr);
21852 AssignmentOps.push_back(
nullptr);
21858 if (!
DSAStack->isThreadPrivate(VD)) {
21860 Diag(ELoc, diag::err_omp_required_access)
21862 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21885 SemaRef.BuildBinOp(
nullptr, DE->getExprLoc(), BO_Assign,
21886 PseudoDstExpr, PseudoSrcExpr);
21895 DSAStack->addDSA(VD, DE, OMPC_copyin);
21896 Vars.push_back(DE);
21897 SrcExprs.push_back(PseudoSrcExpr);
21898 DstExprs.push_back(PseudoDstExpr);
21899 AssignmentOps.push_back(AssignmentOp.
get());
21906 Vars, SrcExprs, DstExprs, AssignmentOps);
21917 for (
Expr *RefExpr : VarList) {
21918 assert(RefExpr &&
"NULL expr in OpenMP copyprivate clause.");
21921 Expr *SimpleRefExpr = RefExpr;
21925 Vars.push_back(RefExpr);
21926 SrcExprs.push_back(
nullptr);
21927 DstExprs.push_back(
nullptr);
21928 AssignmentOps.push_back(
nullptr);
21935 auto *VD = dyn_cast<VarDecl>(D);
21940 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
21941 DSAStackTy::DSAVarData DVar =
21943 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21945 Diag(ELoc, diag::err_omp_wrong_dsa)
21955 if (DVar.CKind == OMPC_unknown) {
21956 DVar =
DSAStack->getImplicitDSA(D,
false);
21957 if (DVar.CKind == OMPC_shared) {
21958 Diag(ELoc, diag::err_omp_required_access)
21960 <<
"threadprivate or private in the enclosing context";
21970 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21972 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
21974 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21977 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21998 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
22001 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
22010 VD ? RefExpr->IgnoreParens()
22012 SrcExprs.push_back(PseudoSrcExpr);
22013 DstExprs.push_back(PseudoDstExpr);
22014 AssignmentOps.push_back(AssignmentOp.
get());
22021 EndLoc, Vars, SrcExprs, DstExprs,
22029 if (VarList.empty())
22038 bool Diagnose =
true) {
22039 QualType OMPDependT = Stack->getOMPDependT();
22040 if (!OMPDependT.
isNull())
22046 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
22049 Stack->setOMPDependT(PT.
get());
22070 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
22075 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
22085struct DoacrossDataInfoTy {
22089 DSAStackTy::OperatorOffsetTy OpsOffs;
22091 llvm::APSInt TotalDepCount;
22094static DoacrossDataInfoTy
22100 DSAStackTy::OperatorOffsetTy OpsOffs;
22101 llvm::APSInt DepCounter(32);
22102 llvm::APSInt TotalDepCount(32);
22104 if (
const Expr *OrderedCountExpr =
22105 Stack->getParentOrderedRegionParam().first) {
22106 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
22107 TotalDepCount.setIsUnsigned(
true);
22110 for (
Expr *RefExpr : VarList) {
22111 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
22114 Vars.push_back(RefExpr);
22121 if (Stack->getParentOrderedRegionParam().first &&
22122 DepCounter >= TotalDepCount) {
22123 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
22137 Vars.push_back(RefExpr);
22144 Expr *RHS =
nullptr;
22145 if (
auto *BO = dyn_cast<BinaryOperator>(
SimpleExpr)) {
22147 OOLoc = BO->getOperatorLoc();
22150 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
SimpleExpr)) {
22151 OOK = OCE->getOperator();
22152 OOLoc = OCE->getOperatorLoc();
22155 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
SimpleExpr)) {
22156 OOK = MCE->getMethodDecl()
22159 .getCXXOverloadedOperator();
22160 OOLoc = MCE->getCallee()->getExprLoc();
22169 Vars.push_back(RefExpr);
22175 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
22176 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
22182 RHS, OMPC_depend,
false);
22187 Stack->getParentOrderedRegionParam().first &&
22188 DepCounter != Stack->isParentLoopControlVariable(D).first) {
22190 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
22192 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
22195 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
22199 OpsOffs.emplace_back(RHS, OOK);
22201 Vars.push_back(RefExpr->IgnoreParenImpCasts());
22204 TotalDepCount > VarList.size() &&
22205 Stack->getParentOrderedRegionParam().first &&
22206 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
22207 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
22208 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
22210 return {Vars, OpsOffs, TotalDepCount};
22219 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
22220 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
22221 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
22225 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
22226 DepKind == OMPC_DEPEND_mutexinoutset) {
22227 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
22230 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
22231 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22233 DepKind == OMPC_DEPEND_sink ||
22235 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22236 DepKind == OMPC_DEPEND_depobj))) {
22238 OMPC_DEPEND_outallmemory,
22239 OMPC_DEPEND_inoutallmemory};
22241 DSAStack->getCurrentDirective() == OMPD_depobj)
22242 Except.push_back(OMPC_DEPEND_depobj);
22244 Except.push_back(OMPC_DEPEND_inoutset);
22246 ?
"depend modifier(iterator) or "
22248 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
22256 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
22258 diag::err_omp_depend_sink_source_with_modifier);
22263 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
22266 DSAStackTy::OperatorOffsetTy OpsOffs;
22267 llvm::APSInt TotalDepCount(32);
22269 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
22272 Vars = VarOffset.Vars;
22273 OpsOffs = VarOffset.OpsOffs;
22274 TotalDepCount = VarOffset.TotalDepCount;
22276 for (
Expr *RefExpr : VarList) {
22277 assert(RefExpr &&
"NULL expr in OpenMP depend clause.");
22280 Vars.push_back(RefExpr);
22286 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
22287 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
22288 if (OMPDependTFound)
22290 DepKind == OMPC_DEPEND_depobj);
22291 if (DepKind == OMPC_DEPEND_depobj) {
22295 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22296 !RefExpr->isInstantiationDependent() &&
22297 !RefExpr->containsUnexpandedParameterPack() &&
22298 (OMPDependTFound &&
22300 DSAStack->getOMPDependT(), RefExpr->getType()))) {
22301 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
22302 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
22305 if (!RefExpr->isLValue()) {
22306 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
22307 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
22314 QualType ExprTy = RefExpr->getType().getNonReferenceType();
22315 const auto *OASE = dyn_cast<ArraySectionExpr>(
SimpleExpr);
22319 if (BaseType.isNull())
22321 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22322 ExprTy = ATy->getElementType();
22325 if (BaseType.isNull() || ExprTy.
isNull())
22328 const Expr *Length = OASE->getLength();
22330 if (Length && !Length->isValueDependent() &&
22332 Result.Val.getInt().isZero()) {
22334 diag::err_omp_depend_zero_length_array_section_not_allowed)
22344 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22345 !RefExpr->isInstantiationDependent() &&
22346 !RefExpr->containsUnexpandedParameterPack() &&
22347 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
22348 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
22350 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
22353 << RefExpr->getSourceRange();
22357 auto *ASE = dyn_cast<ArraySubscriptExpr>(
SimpleExpr);
22358 if (ASE && !ASE->getBase()->isTypeDependent() &&
22361 .getNonReferenceType()
22362 ->isPointerType() &&
22363 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
22364 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
22367 << RefExpr->getSourceRange();
22374 Res =
SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
22375 RefExpr->IgnoreParenImpCasts());
22379 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
22382 << RefExpr->getSourceRange();
22387 Vars.push_back(RefExpr->IgnoreParenImpCasts());
22391 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
22392 DepKind != OMPC_DEPEND_outallmemory &&
22393 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
22398 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
22399 TotalDepCount.getZExtValue());
22400 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
22401 DSAStack->isParentOrderedRegion())
22402 DSAStack->addDoacrossDependClause(
C, OpsOffs);
22411 "Unexpected device modifier in OpenMP < 50.");
22413 bool ErrorFound =
false;
22415 std::string Values =
22417 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22423 Stmt *HelperValStmt =
nullptr;
22435 if (
Value.isInvalid()) {
22438 ValExpr =
Value.get();
22439 if (std::optional<llvm::APSInt>
Result =
22442 Diag(Loc, diag::err_omp_device_expression_invalid)
22460 if (Modifier == OMPC_DEVICE_ancestor) {
22461 if (!
DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
22464 diag::err_omp_device_ancestor_without_requires_reverse_offload);
22472 if (CaptureRegion != OMPD_unknown &&
22473 !
SemaRef.CurContext->isDependentContext()) {
22474 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
22475 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22476 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22481 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
22482 LParenLoc, ModifierLoc, EndLoc);
22487 bool FullCheck =
true) {
22492 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
22502 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22508 (OASE && OASE->getColonLocFirst().isInvalid())) {
22509 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
22510 return ATy->getSExtSize() != 1;
22515 assert(OASE &&
"Expecting array section if not an array subscript.");
22516 const Expr *LowerBound = OASE->getLowerBound();
22517 const Expr *Length = OASE->getLength();
22526 llvm::APSInt ConstLowerBound =
Result.Val.getInt();
22527 if (ConstLowerBound.getSExtValue())
22542 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
22550 llvm::APSInt ConstLength =
Result.Val.getInt();
22551 return CATy->getSExtSize() != ConstLength.getSExtValue();
22560 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22565 (OASE && OASE->getColonLocFirst().isInvalid()))
22568 assert(OASE &&
"Expecting array section if not an array subscript.");
22569 const Expr *Length = OASE->getLength();
22575 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
22576 return ATy->getSExtSize() != 1;
22586 llvm::APSInt ConstLength =
Result.Val.getInt();
22587 return ConstLength.getSExtValue() != 1;
22626class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
22631 bool IsNonContiguous =
false;
22632 bool NoDiagnose =
false;
22633 const Expr *RelevantExpr =
nullptr;
22634 bool AllowUnitySizeArraySection =
true;
22635 bool AllowWholeSizeArraySection =
true;
22636 bool AllowAnotherPtr =
true;
22637 SourceLocation ELoc;
22638 SourceRange ERange;
22640 void emitErrorMsg() {
22642 if (SemaRef.getLangOpts().OpenMP < 50) {
22644 diag::err_omp_expected_named_var_member_or_array_expression)
22647 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22653 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22658 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22659 RelevantExpr = DRE;
22661 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
22665 bool VisitMemberExpr(MemberExpr *ME) {
22670 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22679 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22695 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22715 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22719 return RelevantExpr || Visit(E);
22729 AllowUnitySizeArraySection =
false;
22730 AllowWholeSizeArraySection =
false;
22733 Components.emplace_back(ME, FD, IsNonContiguous);
22734 return RelevantExpr || Visit(E);
22737 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22742 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22746 return RelevantExpr || Visit(E);
22753 AllowWholeSizeArraySection =
false;
22756 Expr::EvalResult
Result;
22759 !
Result.Val.getInt().isZero()) {
22761 diag::err_omp_invalid_map_this_expr);
22763 diag::note_omp_invalid_subscript_on_this_ptr_map);
22765 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22770 Components.emplace_back(AE,
nullptr, IsNonContiguous);
22772 return RelevantExpr || Visit(E);
22775 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22778 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22779 "Array sections cannot be implicitly mapped.");
22793 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22803 if (AllowWholeSizeArraySection) {
22810 if (NotWhole || IsPointer)
22811 AllowWholeSizeArraySection =
false;
22812 }
else if (DKind == OMPD_target_update &&
22813 SemaRef.getLangOpts().OpenMP >= 50) {
22814 if (IsPointer && !AllowAnotherPtr)
22815 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22818 IsNonContiguous =
true;
22819 }
else if (AllowUnitySizeArraySection && NotUnity) {
22825 diag::err_array_section_does_not_specify_contiguous_storage)
22831 AllowAnotherPtr =
false;
22833 if (
const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22834 Expr::EvalResult ResultR;
22835 Expr::EvalResult ResultL;
22840 diag::err_omp_invalid_map_this_expr);
22842 diag::note_omp_invalid_length_on_this_ptr_mapping);
22846 SemaRef.getASTContext()) &&
22849 diag::err_omp_invalid_map_this_expr);
22851 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22853 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22858 Components.emplace_back(OASE,
nullptr,
false);
22859 return RelevantExpr || Visit(E);
22861 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22865 Components.emplace_back(E,
nullptr, IsNonContiguous);
22867 return Visit(
Base->IgnoreParenImpCasts());
22870 bool VisitUnaryOperator(UnaryOperator *UO) {
22871 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
22876 if (!RelevantExpr) {
22878 Components.emplace_back(UO,
nullptr,
false);
22882 bool VisitBinaryOperator(BinaryOperator *BO) {
22894 Components.emplace_back(BO,
nullptr,
false);
22897 "Either LHS or RHS have base decl inside");
22899 return RelevantExpr || Visit(LE);
22900 return RelevantExpr || Visit(RE);
22902 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22903 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22904 RelevantExpr = CTE;
22905 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
22908 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22909 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
22910 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
22913 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22919 return Visit(Source);
22921 bool VisitStmt(Stmt *) {
22925 const Expr *getFoundBase()
const {
return RelevantExpr; }
22926 explicit MapBaseChecker(
22929 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22930 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22931 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22945 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22949 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22950 (CKind == OMPC_to || CKind == OMPC_from)) {
22951 auto CI = CurComponents.rbegin();
22952 auto CE = CurComponents.rend();
22953 for (; CI != CE; ++CI) {
22955 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22960 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
22964 return Checker.getFoundBase();
22973 bool CurrentRegionOnly,
22984 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
22985 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22986 "Map clause expression with unexpected base!");
22989 bool IsEnclosedByDataEnvironmentExpr =
false;
22990 const Expr *EnclosingExpr =
nullptr;
22992 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22993 VD, CurrentRegionOnly,
22994 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22995 ERange, CKind, &EnclosingExpr,
22999 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
23001 assert(!StackComponents.empty() &&
23002 "Map clause expression with no components!");
23003 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
23004 "Map clause expression with unexpected base!");
23008 const Expr *RE = StackComponents.front().getAssociatedExpression();
23014 auto CI = CurComponents.rbegin();
23015 auto CE = CurComponents.rend();
23016 auto SI = StackComponents.rbegin();
23017 auto SE = StackComponents.rend();
23018 for (; CI != CE && SI != SE; ++CI, ++SI) {
23023 if (CurrentRegionOnly &&
23030 SemaRef.
Diag(CI->getAssociatedExpression()->getExprLoc(),
23031 diag::err_omp_multiple_array_items_in_map_clause)
23032 << CI->getAssociatedExpression()->getSourceRange();
23033 SemaRef.
Diag(SI->getAssociatedExpression()->getExprLoc(),
23034 diag::note_used_here)
23035 << SI->getAssociatedExpression()->getSourceRange();
23040 if (CI->getAssociatedExpression()->getStmtClass() !=
23041 SI->getAssociatedExpression()->getStmtClass())
23045 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
23051 for (; SI != SE; ++SI) {
23053 if (
const auto *ASE =
23054 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
23055 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
23056 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
23057 SI->getAssociatedExpression())) {
23060 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
23061 SI->getAssociatedExpression())) {
23066 SemaRef, SI->getAssociatedExpression(),
Type))
23076 if (CI == CE && SI == SE) {
23077 if (CurrentRegionOnly) {
23078 if (CKind == OMPC_map) {
23079 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
23081 assert(CKind == OMPC_to || CKind == OMPC_from);
23082 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
23091 IsEnclosedByDataEnvironmentExpr =
true;
23096 std::prev(CI)->getAssociatedDeclaration()->getType();
23098 std::prev(CI)->getAssociatedExpression()->getExprLoc();
23117 if (CI == CE || SI == SE) {
23120 diag::err_omp_pointer_mapped_along_with_derived_section)
23126 if (CI->getAssociatedExpression()->getStmtClass() !=
23127 SI->getAssociatedExpression()->getStmtClass() ||
23128 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
23129 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
23130 assert(CI != CE && SI != SE);
23131 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
23144 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
23145 if (CKind == OMPC_map) {
23146 if (CI != CE || SI != SE) {
23150 CI != CE ? CurComponents.begin() : StackComponents.begin();
23151 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
23153 while (It != End && !It->getAssociatedDeclaration())
23154 std::advance(It, 1);
23155 assert(It != End &&
23156 "Expected at least one component with the declaration.");
23157 if (It != Begin && It->getAssociatedDeclaration()
23159 .getCanonicalType()
23160 ->isAnyPointerType()) {
23161 IsEnclosedByDataEnvironmentExpr =
false;
23162 EnclosingExpr =
nullptr;
23166 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
23168 assert(CKind == OMPC_to || CKind == OMPC_from);
23169 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
23179 if (!CurrentRegionOnly && SI != SE)
23180 EnclosingExpr = RE;
23184 IsEnclosedByDataEnvironmentExpr |=
23185 (!CurrentRegionOnly && CI != CE && SI == SE);
23190 if (CurrentRegionOnly)
23204 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
23206 diag::err_omp_original_storage_is_shared_and_does_not_contain)
23222 Expr *UnresolvedMapper) {
23242 Lookups.emplace_back();
23243 Lookups.back().append(Lookup.
begin(), Lookup.
end());
23246 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
23251 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
23252 Lookups.back().addDecl(DMD);
23261 return !D->isInvalidDecl() &&
23262 (D->getType()->isDependentType() ||
23263 D->getType()->isInstantiationDependentType() ||
23264 D->getType()->containsUnexpandedParameterPack());
23275 false, URS.
begin(), URS.
end(),
false,
23283 SemaRef.
Diag(Loc, diag::err_omp_mapper_wrong_type);
23324 SemaRef.
Diag(Loc, diag::err_omp_invalid_mapper)
23334struct MappableVarListInfo {
23336 ArrayRef<Expr *> VarList;
23338 SmallVector<Expr *, 16> ProcessedVarList;
23342 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
23344 SmallVector<Expr *, 16> UDMapperList;
23346 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
23349 VarComponents.reserve(VarList.size());
23350 VarBaseDeclarations.reserve(VarList.size());
23359 const RecordDecl *RD = BaseType->getAsRecordDecl();
23369 for (
auto *FD : RD->
fields()) {
23371 MapperVarRef,
false, Range.getBegin(),
23377 SExprs.push_back(BE);
23385 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
23388 Maps.push_back(MapClause);
23389 return MapperVarRef;
23393 DSAStackTy *Stack) {
23399 const RecordDecl *RD = BaseType->getAsRecordDecl();
23408 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
23410 BaseType, MapperId, Maps,
nullptr);
23420 DMD->setMapperVarRef(MapperVarRef);
23444 Lookups.emplace_back();
23445 Lookups.back().append(Lookup.
begin(), Lookup.
end());
23452 return !D->isInvalidDecl() &&
23453 (D->getType()->isDependentType() ||
23454 D->getType()->isInstantiationDependentType() ||
23455 D->getType()->containsUnexpandedParameterPack());
23501 {CanonType,
nullptr});
23502 llvm::DenseMap<const Type *, bool> Visited;
23504 while (!Types.empty()) {
23505 auto [BaseType, CurFD] = Types.pop_back_val();
23506 while (ParentChain.back().second == 0)
23507 ParentChain.pop_back();
23508 --ParentChain.back().second;
23509 if (BaseType.isNull())
23512 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
23515 auto It = Visited.find(BaseType.getTypePtr());
23516 if (It == Visited.end()) {
23525 DefaultMapperId, BaseType);
23526 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
23532 bool FirstIter =
true;
23542 ParentChain.emplace_back(CurFD, 1);
23544 ++ParentChain.back().second;
23546 Types.emplace_back(FieldTy, FD);
23565 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
23568 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23569 CKind == OMPC_use_device_addr) &&
23570 "Unexpected clause kind with mappable expressions!");
23571 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
23579 MapperId.
setName(DeclNames.getIdentifier(
23581 MapperId.
setLoc(StartLoc);
23585 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23586 bool UpdateUMIt =
false;
23587 Expr *UnresolvedMapper =
nullptr;
23589 bool HasHoldModifier =
23590 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
23598 for (
Expr *RE : MVLI.VarList) {
23599 assert(RE &&
"Null expr in omp to/from/map clause");
23603 if (UpdateUMIt && UMIt != UMEnd) {
23607 "Expect the size of UnresolvedMappers to match with that of VarList");
23611 UnresolvedMapper = *UMIt;
23615 if (
VE->isValueDependent() ||
VE->isTypeDependent() ||
23616 VE->isInstantiationDependent() ||
23617 VE->containsUnexpandedParameterPack()) {
23620 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23621 VE->getType().getCanonicalType(), UnresolvedMapper);
23624 MVLI.UDMapperList.push_back(ER.
get());
23627 MVLI.ProcessedVarList.push_back(RE);
23636 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23639 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23652 DSAS->getCurrentDirective(), NoDiagnose);
23656 assert(!CurComponents.empty() &&
23657 "Invalid mappable expression information.");
23659 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23661 DSAS->addMappedClassesQualTypes(TE->getType());
23664 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23665 VE->getType().getCanonicalType(), UnresolvedMapper);
23668 MVLI.UDMapperList.push_back(ER.
get());
23670 MVLI.ProcessedVarList.push_back(RE);
23671 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23672 MVLI.VarComponents.back().append(CurComponents.begin(),
23673 CurComponents.end());
23674 MVLI.VarBaseDeclarations.push_back(
nullptr);
23681 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23682 assert(CurDeclaration &&
"Null decl on map clause.");
23685 "Expecting components to have associated only canonical declarations.");
23687 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23688 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23690 assert((VD || FD) &&
"Only variables or fields are expected here!");
23697 if (VD && DSAS->isThreadPrivate(VD)) {
23700 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23701 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23709 if (VD && CKind == OMPC_map) {
23710 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23711 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
23712 if (*Res == OMPDeclareTargetDeclAttr::MT_Local) {
23715 SemaRef.
Diag(ELoc, diag::err_omp_device_local_in_clause)
23731 true, CurComponents, CKind))
23733 if (CKind == OMPC_map &&
23736 false, CurComponents, CKind))
23743 auto I = llvm::find_if(
23745 [](
const OMPClauseMappableExprCommon::MappableComponent &MC) {
23748 assert(I != CurComponents.end() &&
"Null decl on map clause.");
23751 auto *ASE = dyn_cast<ArraySubscriptExpr>(
VE->IgnoreParens());
23752 auto *OASE = dyn_cast<ArraySectionExpr>(
VE->IgnoreParens());
23753 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(
VE->IgnoreParens());
23755 Type = ASE->getType().getNonReferenceType();
23760 Type = ATy->getElementType();
23763 Type =
Type.getNonReferenceType();
23764 }
else if (OAShE) {
23778 if (CKind == OMPC_map) {
23785 if (DKind == OMPD_target_enter_data &&
23786 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23788 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23789 << (IsMapTypeImplicit ? 1 : 0)
23791 << getOpenMPDirectiveName(DKind, OMPVersion);
23800 if (DKind == OMPD_target_exit_data &&
23801 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23802 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
23803 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23804 << (IsMapTypeImplicit ? 1 : 0)
23806 << getOpenMPDirectiveName(DKind, OMPVersion);
23815 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23817 SemaRef.
Diag(StartLoc,
23818 diag::err_omp_invalid_map_type_modifier_for_directive)
23820 OMPC_MAP_MODIFIER_ompx_hold)
23821 << getOpenMPDirectiveName(DKind, OMPVersion);
23829 if ((DKind == OMPD_target_data ||
23831 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23832 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23833 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23834 << (IsMapTypeImplicit ? 1 : 0)
23836 << getOpenMPDirectiveName(DKind, OMPVersion);
23848 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
23850 DKind == OMPD_target)) {
23851 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
23853 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23856 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23866 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23867 Type.getCanonicalType(), UnresolvedMapper);
23879 BaseType =
VE->getType().getCanonicalType();
23886 ElemType = ATy->getElementType();
23891 }
else if (
VE->getType()->isArrayType()) {
23892 const ArrayType *AT =
VE->getType()->getAsArrayTypeUnsafe();
23902 MVLI.UDMapperList.push_back(ER.
get());
23905 MVLI.ProcessedVarList.push_back(RE);
23909 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23915 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23916 MVLI.VarComponents.back().append(CurComponents.begin(),
23917 CurComponents.end());
23939 BuiltinType::OMPIterator))
23941 diag::err_omp_map_modifier_not_iterator);
23944 unsigned Count = 0;
23945 for (
unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23947 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23948 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23952 "Modifiers exceed the allowed number of map type modifiers");
23953 Modifiers[Count] = MapTypeModifiers[I];
23954 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23958 MappableVarListInfo MVLI(VarList);
23964 for (
auto *E : VarList) {
23965 if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
23967 MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
23970 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23971 MapType, Modifiers, IsMapTypeImplicit,
23977 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23978 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23980 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23988 if (ReductionType.
isNull())
23996 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
24001 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
24005 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
24009 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
24012 return ReductionType;
24018 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
24021 Decls.reserve(ReductionTypes.size());
24025 SemaRef.forRedeclarationInCurContext());
24030 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24032 bool InCompoundScope =
true;
24033 if (S !=
nullptr) {
24039 SemaRef.LookupName(Lookup, S);
24040 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
24042 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
24044 while (Filter.hasNext()) {
24046 if (InCompoundScope) {
24047 UsedAsPrevious.try_emplace(PrevDecl,
false);
24049 UsedAsPrevious[D] =
true;
24051 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24052 PrevDecl->getLocation();
24055 if (InCompoundScope) {
24056 for (
const auto &PrevData : UsedAsPrevious) {
24057 if (!PrevData.second) {
24058 PrevDRD = PrevData.first;
24063 }
else if (PrevDeclInScope !=
nullptr) {
24064 auto *PrevDRDInScope = PrevDRD =
24067 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
24068 PrevDRDInScope->getLocation();
24069 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
24070 }
while (PrevDRDInScope !=
nullptr);
24072 for (
const auto &TyData : ReductionTypes) {
24073 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
24075 if (I != PreviousRedeclTypes.end()) {
24076 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
24078 Diag(I->second, diag::note_previous_definition);
24081 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
24083 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
24085 DRD->setAccess(AS);
24086 Decls.push_back(DRD);
24088 DRD->setInvalidDecl();
24102 SemaRef.setFunctionHasBranchProtectedScope();
24103 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
24106 SemaRef.PushDeclContext(S, DRD);
24110 SemaRef.PushExpressionEvaluationContext(
24113 QualType ReductionType = DRD->getType();
24130 if (S !=
nullptr) {
24131 SemaRef.PushOnScopeChains(OmpInParm, S);
24132 SemaRef.PushOnScopeChains(OmpOutParm, S);
24134 DRD->addDecl(OmpInParm);
24135 DRD->addDecl(OmpOutParm);
24141 DRD->setCombinerData(InE, OutE);
24147 SemaRef.DiscardCleanupsInEvaluationContext();
24148 SemaRef.PopExpressionEvaluationContext();
24151 SemaRef.PopFunctionScopeInfo();
24153 if (Combiner !=
nullptr)
24154 DRD->setCombiner(Combiner);
24156 DRD->setInvalidDecl();
24165 SemaRef.setFunctionHasBranchProtectedScope();
24168 SemaRef.PushDeclContext(S, DRD);
24172 SemaRef.PushExpressionEvaluationContext(
24175 QualType ReductionType = DRD->getType();
24192 if (S !=
nullptr) {
24193 SemaRef.PushOnScopeChains(OmpPrivParm, S);
24194 SemaRef.PushOnScopeChains(OmpOrigParm, S);
24196 DRD->addDecl(OmpPrivParm);
24197 DRD->addDecl(OmpOrigParm);
24203 DRD->setInitializerData(OrigE, PrivE);
24204 return OmpPrivParm;
24210 SemaRef.DiscardCleanupsInEvaluationContext();
24211 SemaRef.PopExpressionEvaluationContext();
24214 SemaRef.PopFunctionScopeInfo();
24218 }
else if (OmpPrivParm->
hasInit()) {
24219 DRD->setInitializer(OmpPrivParm->
getInit(),
24224 DRD->setInvalidDecl();
24230 for (
Decl *D : DeclReductions.
get()) {
24236 D->setInvalidDecl();
24239 return DeclReductions;
24251 SemaRef.CheckExtraCXXDefaultArguments(D);
24254 return SemaRef.CreateParsedType(T, TInfo);
24259 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
24262 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
24267 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
24279 SemaRef.forRedeclarationInCurContext());
24284 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24286 bool InCompoundScope =
true;
24287 if (S !=
nullptr) {
24293 SemaRef.LookupName(Lookup, S);
24294 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
24296 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
24298 while (Filter.hasNext()) {
24300 if (InCompoundScope) {
24301 UsedAsPrevious.try_emplace(PrevDecl,
false);
24303 UsedAsPrevious[D] =
true;
24305 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24306 PrevDecl->getLocation();
24309 if (InCompoundScope) {
24310 for (
const auto &PrevData : UsedAsPrevious) {
24311 if (!PrevData.second) {
24312 PrevDMD = PrevData.first;
24317 }
else if (PrevDeclInScope) {
24318 auto *PrevDMDInScope = PrevDMD =
24321 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
24322 PrevDMDInScope->getLocation();
24323 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
24324 }
while (PrevDMDInScope !=
nullptr);
24328 if (I != PreviousRedeclTypes.end()) {
24329 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
24330 << MapperType << Name;
24331 Diag(I->second, diag::note_previous_definition);
24339 ClausesWithImplicit);
24341 MapperType, VN, ClausesWithImplicit,
24344 SemaRef.PushOnScopeChains(DMD, S);
24347 DMD->setAccess(AS);
24349 DMD->setInvalidDecl();
24355 DMD->setMapperVarRef(MapperVarRef);
24369 SemaRef.PushOnScopeChains(VD, S,
false);
24371 DSAStack->addDeclareMapperVarRef(E);
24378 if (
DSAStack->getDeclareMapperVarRef()) {
24384 assert(!IsGlobalVar &&
"Only declare mapper handles TU-scope iterators.");
24389 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
24391 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
24404 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
24412 if (VarList.empty())
24415 for (
Expr *ValExpr : VarList) {
24426 if (ModifierExpr) {
24427 assert(Modifier == OMPC_NUMTEAMS_lower_bound &&
"Unexpected modifier.");
24430 Diag(ModifierLoc, diag::err_omp_modifier_requires_version)
24432 << getOpenMPClauseName(llvm::omp::OMPC_num_teams) <<
"5.1";
24441 Expr *LowerBound = ModifierExpr;
24442 Expr *UpperBound = VarList[0];
24450 llvm::APSInt LowerVal =
24452 llvm::APSInt UpperVal =
24455 if (LowerVal > UpperVal) {
24457 diag::err_omp_num_teams_lower_bound_larger)
24467 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
24469 LParenLoc, EndLoc, VarList, Modifier,
24470 ModifierExpr, ModifierLoc,
24473 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24475 for (
Expr *ValExpr : VarList) {
24476 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24477 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24478 Vars.push_back(ValExpr);
24481 if (ModifierExpr) {
24482 ModifierExpr =
SemaRef.MakeFullExpr(ModifierExpr).get();
24483 ModifierExpr = tryBuildCapture(
SemaRef, ModifierExpr, Captures).get();
24488 LParenLoc, EndLoc, Vars, Modifier,
24489 ModifierExpr, ModifierLoc, PreInit);
24496 if (VarList.empty())
24499 for (
Expr *ValExpr : VarList) {
24510 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
24512 StartLoc, LParenLoc, EndLoc, VarList,
24515 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24517 for (
Expr *ValExpr : VarList) {
24518 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24519 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24520 Vars.push_back(ValExpr);
24525 LParenLoc, EndLoc, Vars, PreInit);
24532 Expr *ValExpr = Priority;
24533 Stmt *HelperValStmt =
nullptr;
24539 ValExpr,
SemaRef, OMPC_priority,
24541 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24545 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24553 "Unexpected grainsize modifier in OpenMP < 51.");
24558 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24563 Expr *ValExpr = Grainsize;
24564 Stmt *HelperValStmt =
nullptr;
24574 &CaptureRegion, &HelperValStmt))
24579 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24587 "Unexpected num_tasks modifier in OpenMP < 51.");
24592 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24597 Expr *ValExpr = NumTasks;
24598 Stmt *HelperValStmt =
nullptr;
24605 ValExpr,
SemaRef, OMPC_num_tasks,
24607 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24612 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24632 DSAStackTy *Stack) {
24633 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
24634 if (!OMPEventHandleT.
isNull())
24639 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
24642 Stack->setOMPEventHandleT(PT.
get());
24663 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
24673 <<
"omp_event_handle_t" << 1 << VD->
getType()
24680 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
24681 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24700 std::string Values;
24704 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24708 Expr *ValExpr = ChunkSize;
24709 Stmt *HelperValStmt =
nullptr;
24720 ValExpr = Val.
get();
24725 if (std::optional<llvm::APSInt>
Result =
24727 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
24728 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24729 <<
"dist_schedule" << 1
24734 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24736 !
SemaRef.CurContext->isDependentContext()) {
24737 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24738 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24739 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24747 Kind, ValExpr, HelperValStmt);
24755 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24756 Kind != OMPC_DEFAULTMAP_scalar) {
24760 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24762 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24766 OMPC_DEFAULTMAP_scalar);
24770 Diag(Loc, diag::err_omp_unexpected_clause_value)
24778 if (!isDefaultmapKind || !isDefaultmapModifier) {
24780 ?
"'scalar', 'aggregate', 'pointer'"
24781 :
"'scalar', 'aggregate', 'pointer', 'all'";
24783 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
24784 "'firstprivate', 'none', 'default'";
24785 if (!isDefaultmapKind && isDefaultmapModifier) {
24786 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24788 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24789 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24792 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24794 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24798 StringRef ModifierValue =
24800 ?
"'alloc', 'from', 'to', 'tofrom', "
24801 "'firstprivate', 'none', 'default', 'present'"
24802 :
"'storage', 'from', 'to', 'tofrom', "
24803 "'firstprivate', 'private', 'none', 'default', 'present'";
24804 if (!isDefaultmapKind && isDefaultmapModifier) {
24805 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24807 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
24808 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24811 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24813 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24823 if (
DSAStack->checkDefaultmapCategory(Kind)) {
24824 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24830 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24831 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24832 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24834 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24851 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
24857 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
24859 DeclareTargetNesting.push_back(DTCI);
24865 assert(!DeclareTargetNesting.empty() &&
24866 "check isInOpenMPDeclareTargetContext() first!");
24867 return DeclareTargetNesting.pop_back_val();
24877 if (DeclareTargetNesting.empty())
24881 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
24882 << getOpenMPDirectiveName(DTCI.
Kind, OMPVersion);
24888 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24897 VarOrFuncDeclFilterCCC CCC(
SemaRef);
24901 SemaRef.diagnoseTypo(Corrected,
24902 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24926 "Expected variable, function or function template.");
24928 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
24930 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24931 !VD->isStaticDataMember()) {
24932 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24941 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24945 Diag(Loc, diag::warn_hip_omp_target_directives);
24949 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
24950 DTCI.
DT == OMPDeclareTargetDeclAttr::DT_Host) {
24951 Diag(Loc, diag::err_omp_declare_target_local_host_only);
24956 const unsigned Level = -1;
24959 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24960 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24961 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
24962 (*ActiveAttr)->getLevel() == Level) {
24963 Diag(Loc, diag::err_omp_device_type_mismatch)
24964 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
24965 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24966 (*ActiveAttr)->getDevType());
24969 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24970 (*ActiveAttr)->getLevel() == Level) {
24971 Diag(Loc, diag::err_omp_declare_target_var_in_both_clauses)
24973 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
24974 (*ActiveAttr)->getMapType())
24975 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(MT);
24979 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24982 Expr *IndirectE =
nullptr;
24983 bool IsIndirect =
false;
24993 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
24994 DT == OMPDeclareTargetDeclAttr::DT_NoHost) {
24995 Diag(Loc, diag::warn_omp_declare_target_local_nohost);
24996 DT = OMPDeclareTargetDeclAttr::DT_Any;
24999 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25004 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
25006 if (
auto *VD = dyn_cast<VarDecl>(ND);
25008 VD->hasGlobalStorage())
25017 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
25018 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
25019 if (SemaRef.
LangOpts.OpenMP >= 50 &&
25022 VD->hasGlobalStorage()) {
25023 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
25024 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
25025 *
MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
25032 diag::err_omp_lambda_capture_in_declare_target_not_to);
25033 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
25040 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
25041 SemaRef.
Diag(SL, diag::note_used_here) << SR;
25045 Sema &SemaRef, DSAStackTy *Stack,
25047 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
25058 if (
auto *VD = dyn_cast<VarDecl>(D)) {
25060 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
25061 !VD->isStaticDataMember())
25065 if (
DSAStack->isThreadPrivate(VD)) {
25066 Diag(SL, diag::err_omp_threadprivate_in_target);
25071 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
25072 D = FTD->getTemplatedDecl();
25073 if (
auto *FD = dyn_cast<FunctionDecl>(D)) {
25074 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
25075 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
25076 if (IdLoc.
isValid() && Res &&
25077 (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
25078 *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
25079 Diag(IdLoc, diag::err_omp_function_in_target_clause_list)
25080 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(*Res);
25085 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
25095 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
25096 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
25097 unsigned Level = DeclareTargetNesting.size();
25098 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
25101 Expr *IndirectE =
nullptr;
25102 bool IsIndirect =
false;
25108 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25110 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
25111 : OMPDeclareTargetDeclAttr::MT_To,
25112 DTCI.
DT, IndirectE, IsIndirect, Level,
25116 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
25136 if (
auto *VD = dyn_cast<VarDecl>(Node->
getDecl())) {
25138 DeclVector.push_back(VD);
25143 for (
auto *Child : Ex->
children()) {
25152 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
25154 llvm::SmallDenseSet<Decl *> Visited;
25155 while (!DeclVector.empty()) {
25156 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
25157 if (!Visited.insert(TargetVarDecl).second)
25160 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
25190 unsigned Count = 0;
25191 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25193 llvm::is_contained(Modifiers, MotionModifiers[I])) {
25194 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
25198 "Modifiers exceed the allowed number of motion modifiers");
25199 Modifiers[Count] = MotionModifiers[I];
25200 ModifiersLoc[Count] = MotionModifiersLoc[I];
25204 MappableVarListInfo MVLI(VarList);
25206 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25207 if (MVLI.ProcessedVarList.empty())
25210 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
25211 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
25214 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25215 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
25232 unsigned Count = 0;
25233 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25235 llvm::is_contained(Modifiers, MotionModifiers[I])) {
25236 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
25240 "Modifiers exceed the allowed number of motion modifiers");
25241 Modifiers[Count] = MotionModifiers[I];
25242 ModifiersLoc[Count] = MotionModifiersLoc[I];
25246 MappableVarListInfo MVLI(VarList);
25248 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25249 if (MVLI.ProcessedVarList.empty())
25252 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
25253 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
25256 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25257 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
25266 MappableVarListInfo MVLI(VarList);
25270 for (
Expr *RefExpr : VarList) {
25271 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
25274 Expr *SimpleRefExpr = RefExpr;
25278 MVLI.ProcessedVarList.push_back(RefExpr);
25279 PrivateCopies.push_back(
nullptr);
25280 Inits.push_back(
nullptr);
25287 Type =
Type.getNonReferenceType().getUnqualifiedType();
25289 auto *VD = dyn_cast<VarDecl>(D);
25293 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
25294 << 0 << RefExpr->getSourceRange();
25303 if (VDPrivate->isInvalidDecl())
25306 SemaRef.CurContext->addDecl(VDPrivate);
25308 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
25315 SemaRef.AddInitializerToDecl(
25316 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
25324 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
25325 PrivateCopies.push_back(VDPrivateRefExpr);
25326 Inits.push_back(VDInitRefExpr);
25331 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
25335 MVLI.VarBaseDeclarations.push_back(D);
25336 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25337 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
25341 if (MVLI.ProcessedVarList.empty())
25346 MVLI.VarBaseDeclarations, MVLI.VarComponents, FallbackModifier,
25347 FallbackModifierLoc);
25353 MappableVarListInfo MVLI(VarList);
25355 for (
Expr *RefExpr : VarList) {
25356 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
25359 Expr *SimpleRefExpr = RefExpr;
25365 MVLI.ProcessedVarList.push_back(RefExpr);
25370 auto *VD = dyn_cast<VarDecl>(D);
25377 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
25382 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
25388 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
25395 assert(!CurComponents.empty() &&
25396 "use_device_addr clause expression with no components!");
25413 CurComponents,
DSAStack->getCurrentDirective());
25414 const Expr *AttachPtrExpr = AttachPtrResult.first;
25416 if (AttachPtrExpr) {
25418 bool IsValidBase =
false;
25421 IsValidBase =
true;
25422 else if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
25424 IsValidBase =
true;
25426 if (!IsValidBase) {
25428 diag::err_omp_expected_base_pointer_var_name_member_expr)
25429 << (
SemaRef.getCurrentThisType().isNull() ? 0 : 1)
25436 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
25438 "Unexpected null decl for use_device_addr clause.");
25440 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
25441 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25442 MVLI.VarComponents.back().append(CurComponents.begin(),
25443 CurComponents.end());
25446 if (MVLI.ProcessedVarList.empty())
25450 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25451 MVLI.VarComponents);
25457 MappableVarListInfo MVLI(VarList);
25458 for (
Expr *RefExpr : VarList) {
25459 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
25462 Expr *SimpleRefExpr = RefExpr;
25466 MVLI.ProcessedVarList.push_back(RefExpr);
25476 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
25477 << 0 << RefExpr->getSourceRange();
25483 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
25486 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
25489 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
25495 const Expr *ConflictExpr;
25496 if (
DSAStack->checkMappableExprComponentListsForDecl(
25501 ConflictExpr = R.front().getAssociatedExpression();
25504 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25513 SimpleRefExpr, D,
false);
25514 DSAStack->addMappableExpressionComponents(
25515 D, MC, OMPC_is_device_ptr);
25518 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
25525 "Unexpected device pointer expression!");
25526 MVLI.VarBaseDeclarations.push_back(
25528 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25529 MVLI.VarComponents.back().push_back(MC);
25532 if (MVLI.ProcessedVarList.empty())
25536 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25537 MVLI.VarComponents);
25543 MappableVarListInfo MVLI(VarList);
25544 for (
Expr *RefExpr : VarList) {
25545 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
25548 Expr *SimpleRefExpr = RefExpr;
25553 MVLI.ProcessedVarList.push_back(RefExpr);
25561 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
25564 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
25567 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
25573 const Expr *ConflictExpr;
25574 if (
DSAStack->checkMappableExprComponentListsForDecl(
25579 ConflictExpr = R.front().getAssociatedExpression();
25582 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25590 Expr *Component = SimpleRefExpr;
25591 auto *VD = dyn_cast<VarDecl>(D);
25595 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
25597 Component, D,
false);
25598 DSAStack->addMappableExpressionComponents(
25599 D, MC, OMPC_has_device_addr);
25602 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
25605 assert(Ref &&
"has_device_addr capture failed");
25606 MVLI.ProcessedVarList.push_back(Ref);
25608 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
25615 "Unexpected device pointer expression!");
25616 MVLI.VarBaseDeclarations.push_back(
25618 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25619 MVLI.VarComponents.back().push_back(MC);
25622 if (MVLI.ProcessedVarList.empty())
25626 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25627 MVLI.VarComponents);
25641 bool AllocDependent =
25645 if (!AllocDependent) {
25654 AllocatorRes =
SemaRef.PerformImplicitConversion(
25655 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
25660 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
25669 !
DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
25670 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
25677 if (!AlignmentDependent) {
25680 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
25685 for (
Expr *RefExpr : VarList) {
25686 assert(RefExpr &&
"NULL expr in OpenMP allocate clause.");
25689 Expr *SimpleRefExpr = RefExpr;
25693 Vars.push_back(RefExpr);
25699 auto *VD = dyn_cast<VarDecl>(D);
25701 if (!VD && !
SemaRef.CurContext->isDependentContext())
25703 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
25704 ? RefExpr->IgnoreParens()
25712 DSAStack->addInnerAllocatorExpr(Allocator);
25715 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25716 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
25717 SecondAllocateModifierLoc, EndLoc, Vars);
25725 for (
Expr *RefExpr : VarList) {
25726 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
25729 Expr *SimpleRefExpr = RefExpr;
25733 Vars.push_back(RefExpr);
25740 if (
const Expr *PrevRef =
25741 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
25742 Diag(ELoc, diag::err_omp_used_in_clause_twice)
25744 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
25749 Vars.push_back(RefExpr);
25766 SemaRef.setFunctionHasBranchProtectedScope();
25768 return OMPScopeDirective::Create(
getASTContext(), StartLoc, EndLoc, Clauses,
25777 for (
Expr *RefExpr : VarList) {
25778 assert(RefExpr &&
"NULL expr in OpenMP inclusive clause.");
25781 Expr *SimpleRefExpr = RefExpr;
25786 Vars.push_back(RefExpr);
25791 const DSAStackTy::DSAVarData DVar =
25797 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25798 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25799 << RefExpr->getSourceRange();
25801 if (
DSAStack->getParentDirective() != OMPD_unknown)
25802 DSAStack->markDeclAsUsedInScanDirective(D);
25803 Vars.push_back(RefExpr);
25818 for (
Expr *RefExpr : VarList) {
25819 assert(RefExpr &&
"NULL expr in OpenMP exclusive clause.");
25822 Expr *SimpleRefExpr = RefExpr;
25827 Vars.push_back(RefExpr);
25833 DSAStackTy::DSAVarData DVar;
25834 if (ParentDirective != OMPD_unknown)
25835 DVar =
DSAStack->getTopDSA(D,
true);
25840 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25841 DVar.Modifier != OMPC_REDUCTION_inscan) {
25842 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25843 << RefExpr->getSourceRange();
25845 DSAStack->markDeclAsUsedInScanDirective(D);
25847 Vars.push_back(RefExpr);
25859 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25860 if (!OMPAlloctraitT.
isNull())
25865 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
25868 Stack->setOMPAlloctraitT(PT.
get());
25888 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25889 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
25890 StringRef Allocator =
25891 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25893 PredefinedAllocators.insert(
SemaRef.LookupSingleName(
25899 Expr *AllocatorExpr =
nullptr;
25907 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25908 bool IsPredefinedAllocator =
false;
25910 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25912 IsPredefinedAllocator =
25914 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25918 bool IsTypeCompatible = IsPredefinedAllocator;
25919 IsTypeCompatible = IsTypeCompatible ||
25920 Context.hasSameUnqualifiedType(AllocatorExprType,
25921 OMPAllocatorHandleT);
25923 IsTypeCompatible ||
25924 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25925 bool IsNonConstantLValue =
25927 if (!DRE || !IsTypeCompatible ||
25928 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25930 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
25939 diag::err_omp_predefined_allocator_with_traits)
25952 diag::err_omp_nonpredefined_allocator_without_traits);
25958 AllocatorExpr =
SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25961 IsPredefinedAllocator
25962 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25963 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25965 Expr *AllocatorTraitsExpr =
nullptr;
25979 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25980 TraitTy = ConstArrayTy->getElementType();
25982 !(Context.hasSameUnqualifiedType(TraitTy,
25984 Context.typesAreCompatible(TraitTy,
DSAStack->getOMPAlloctraitT(),
25987 diag::err_omp_expected_array_alloctraits)
25988 << AllocatorTraitsExpr->
getType();
25993 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25996 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
26013 for (
Expr *RefExpr : Locators) {
26014 assert(RefExpr &&
"NULL expr in OpenMP affinity clause.");
26017 Vars.push_back(RefExpr);
26025 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
26026 << 1 << 0 << RefExpr->getSourceRange();
26037 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
26038 << 1 << 0 << RefExpr->getSourceRange();
26045 ColonLoc, EndLoc, Modifier, Vars);
26054 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26062 LParenLoc, EndLoc);
26069 Expr *ValExpr = Size;
26070 Stmt *HelperValStmt =
nullptr;
26081 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
26082 if (CaptureRegion != OMPD_unknown &&
26083 !
SemaRef.CurContext->isDependentContext()) {
26084 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
26085 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26086 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
26091 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
26106 diag::err_omp_unexpected_clause_value)
26107 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
26111 Expr *ValExpr = Size;
26112 Stmt *HelperValStmt =
nullptr;
26123 DKind, OMPC_dyn_groupprivate,
getLangOpts().OpenMP);
26124 if (CaptureRegion != OMPD_unknown &&
26125 !
SemaRef.CurContext->isDependentContext()) {
26126 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
26127 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26128 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
26133 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
26142 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
26143 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
26144 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
26145 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
26146 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
26152 DSAStackTy::OperatorOffsetTy OpsOffs;
26153 llvm::APSInt TotalDepCount(32);
26156 DepType == OMPC_DOACROSS_source ||
26157 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
26158 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
26160 Vars = VarOffset.Vars;
26161 OpsOffs = VarOffset.OpsOffs;
26162 TotalDepCount = VarOffset.TotalDepCount;
26164 EndLoc, DepType, DepLoc, ColonLoc, Vars,
26165 TotalDepCount.getZExtValue());
26166 if (
DSAStack->isParentOrderedRegion())
26167 DSAStack->addDoacrossDependClause(
C, OpsOffs);
26187 return new (
getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
26195 return OMPAbsentClause::Create(
getASTContext(), DKVec, Loc, LLoc, RLoc);
26196 case OMPC_contains:
26197 return OMPContainsClause::Create(
getASTContext(), DKVec, Loc, LLoc, RLoc);
26199 llvm_unreachable(
"Unexpected OpenMP clause");
26207 case OMPC_no_openmp:
26209 case OMPC_no_openmp_routines:
26210 return new (
getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
26211 case OMPC_no_parallelism:
26212 return new (
getASTContext()) OMPNoParallelismClause(Loc, RLoc);
26213 case OMPC_no_openmp_constructs:
26214 return new (
getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
26216 llvm_unreachable(
"Unexpected OpenMP clause");
26225 if (
Base->hasPlaceholderType() &&
26226 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
26239 LowerBound =
Result.get();
26241 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
26261 if (
Base->isTypeDependent() ||
26264 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
26267 Base, LowerBound, Length, Stride, Context.DependentTy,
VK_LValue,
26268 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26280 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
26281 <<
Base->getSourceRange());
26287 if (Res.isInvalid())
26289 diag::err_omp_typecheck_section_not_integer)
26291 LowerBound = Res.get();
26301 if (Res.isInvalid())
26303 diag::err_omp_typecheck_section_not_integer)
26304 << 1 << Length->getSourceRange());
26305 Length = Res.get();
26307 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
26308 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
26309 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
26310 << 1 << Length->getSourceRange();
26317 diag::err_omp_typecheck_section_not_integer)
26319 Stride = Res.
get();
26332 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
26333 << ResultTy <<
Base->getSourceRange();
26337 if (
SemaRef.RequireCompleteType(
Base->getExprLoc(), ResultTy,
26338 diag::err_omp_section_incomplete_type,
Base))
26346 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
26347 if (LowerBoundValue.isNegative()) {
26349 diag::err_omp_section_not_subset_of_array)
26358 if (Length->EvaluateAsInt(
Result, Context)) {
26361 llvm::APSInt LengthValue =
Result.Val.getInt();
26362 if (LengthValue.isNegative()) {
26363 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
26364 <<
toString(LengthValue, 10,
true)
26365 << Length->getSourceRange();
26369 }
else if (
SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.
isValid() &&
26375 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
26385 llvm::APSInt StrideValue =
Result.Val.getInt();
26386 if (!StrideValue.isStrictlyPositive()) {
26387 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
26388 <<
toString(StrideValue, 10,
true)
26395 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
26402 Base, LowerBound, Length, Stride, Context.ArraySectionTy,
VK_LValue,
26403 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26410 if (
Base->hasPlaceholderType()) {
26424 LParenLoc, RParenLoc, Dims, Brackets);
26426 (!
Base->isTypeDependent() &&
26429 diag::err_omp_non_pointer_type_array_shaping_base)
26430 <<
Base->getSourceRange());
26433 bool ErrorFound =
false;
26435 if (
Dim->hasPlaceholderType()) {
26437 if (
Result.isInvalid()) {
26442 if (
Result.isInvalid()) {
26448 if (!
Dim->isTypeDependent()) {
26451 if (
Result.isInvalid()) {
26453 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
26454 <<
Dim->getSourceRange();
26459 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
26464 if (!
Value.isStrictlyPositive()) {
26465 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
26467 <<
Dim->getSourceRange();
26473 NewDims.push_back(
Dim);
26478 LParenLoc, RParenLoc, NewDims, Brackets);
26488 bool IsCorrect =
true;
26493 if (!D.Type.getAsOpaquePtr()) {
26497 DeclTy = Context.IntTy;
26498 StartLoc = D.DeclIdentLoc;
26504 bool IsDeclTyDependent = DeclTy->isDependentType() ||
26505 DeclTy->containsUnexpandedParameterPack() ||
26506 DeclTy->isInstantiationDependentType();
26507 if (!IsDeclTyDependent) {
26508 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
26511 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
26516 if (DeclTy.isConstant(Context)) {
26519 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
26527 assert(D.DeclIdent &&
"Identifier expected.");
26532 D.DeclIdent, DeclTy, TInfo,
SC_None);
26550 SemaRef.PushOnScopeChains(VD, S);
26553 SemaRef.CurContext->addDecl(VD);
26559 Expr *Begin = D.Range.Begin;
26563 Begin = BeginRes.
get();
26565 Expr *End = D.Range.End;
26569 End = EndRes.
get();
26571 Expr *Step = D.Range.Step;
26574 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
26579 std::optional<llvm::APSInt>
Result =
26585 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
26591 if (!Begin || !End || !IsCorrect) {
26607 if (
Decl *ID = D.IteratorDecl)
26608 ID->setInvalidDecl();
26613 if (!
SemaRef.CurContext->isDependentContext()) {
26620 D.Range.End, D.Range.Begin);
26626 if (D.Range.Step) {
26629 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.
get(),
26636 Res =
SemaRef.CreateBuiltinBinOp(
26637 D.AssignmentLoc, BO_Sub, Res.
get(),
26638 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26644 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.
get(),
26650 St1 =
SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
26654 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
26660 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.
get(),
26667 Res1 =
SemaRef.CreateBuiltinBinOp(
26668 D.AssignmentLoc, BO_Sub, Res1.
get(),
26669 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26675 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.
get(),
26683 D.AssignmentLoc, BO_GT, D.Range.Step,
26684 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
26689 Res =
SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
26696 Res =
SemaRef.ActOnFinishFullExpr(Res.
get(),
false);
26708 CounterVD->setImplicit();
26715 if (D.Range.Step) {
26716 UpdateRes =
SemaRef.CreateBuiltinBinOp(
26717 D.AssignmentLoc, BO_Mul,
26718 SemaRef.DefaultLvalueConversion(RefRes.
get()).get(), St.
get());
26720 UpdateRes =
SemaRef.DefaultLvalueConversion(RefRes.
get());
26726 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
26727 D.Range.Begin, UpdateRes.
get());
26736 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
26737 VDRes.
get(), UpdateRes.
get());
26743 SemaRef.ActOnFinishFullExpr(UpdateRes.
get(),
true);
26749 D.AssignmentLoc, UO_PreInc, RefRes.
get());
26750 if (!CounterUpdateRes.
isUsable()) {
26754 CounterUpdateRes =
SemaRef.ActOnFinishFullExpr(CounterUpdateRes.
get(),
26756 if (!CounterUpdateRes.
isUsable()) {
26767 Helpers.assign(ID.size(), {});
26772 if (
Decl *ID = D.IteratorDecl)
26773 ID->setInvalidDecl();
26778 LLoc, RLoc, ID, Helpers);
26783 StringRef AssumptionStr) {
26784 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26787 unsigned BestEditDistance = 3;
26788 StringRef Suggestion;
26789 for (
const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26790 unsigned EditDistance =
26791 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26792 if (EditDistance < BestEditDistance) {
26793 Suggestion = KnownAssumptionIt.getKey();
26794 BestEditDistance = EditDistance;
26798 if (!Suggestion.empty())
26799 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26800 << AssumptionStr << Suggestion;
26802 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26810 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
Result
Implement __builtin_bit_cast and related operations.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::TargetList TargetList
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static bool hasConstQualifiedMappingType(QualType T)
static void updatePreInits(OMPLoopTransformationDirective *Transform, SmallVectorImpl< Stmt * > &PreInits)
Updates OriginalInits by checking Transform against loop transformation directives and appending thei...
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static OMPClause * createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg, Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls, llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopInductionVars)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static bool checkExprsInMultidimClause(SemaBase &SemaRef, const ClauseT *Clause, const OMPXBareClause *BareClause)
Check the number of expressions specified in a multidimensional clause and return whether an error wa...
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, bool AllowAssumedSizeArray=false, StringRef DiagType="")
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkMultidimClauses(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, bool MayHaveBareClause=false)
Check the number of expressions specified in clauses that can contain multidimensional values,...
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static bool hasNoMutableFields(const CXXRecordDecl *RD)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget, bool HasConstQualifier)
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propagated from the selected loop.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
Expr * getV()
Get 'v' part of the associated expression/statement.
Expr * getR()
Get 'r' part of the associated expression/statement.
Expr * getD()
Get 'd' part of the associated expression/statement.
Expr * getX()
Get 'x' part of the associated expression/statement.
bool isFailOnly() const
Return true if 'v' is updated only when the condition is evaluated false (compare capture only).
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
static QualType getPointeeType(const MemRegion *R)
VerifyDiagnosticConsumer::Directive Directive
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override
bool VisitVarDecl(VarDecl *D) override
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F) override
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override
NestedLoopCounterVisitor()=default
bool VisitForStmt(ForStmt *FS) override
bool TraverseStmt(Stmt *S) override
bool TraverseDecl(Decl *D) override
unsigned getNestedLoopCount() const
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Class that represents a component of a mappable expression. E.g. for an expression S....
ValueDecl * getAssociatedDeclaration() const
SmallVector< MappableComponent, 8 > MappableExprComponentList
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents 'defaultmap' clause in the 'pragma omp ...' directive.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorExpr, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
static OMPFuseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumGeneratedTopLevelLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for pragma omp fuse'.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the 'pragma omp ...' directive.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'nocontext' clause in the 'pragma omp ...' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, OpenMPNumTeamsClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'order' clause in the 'pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'priority' clause in the 'pragma omp ...' directive.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, unsigned NumLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp reverse'.
This represents 'simd' clause in the 'pragma omp ...' directive.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPSplitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp split'.
static OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp stripe'.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'threads' clause in the 'pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp tile'.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedTopLevelLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp unroll'.
This represents the 'use' clause in 'pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Creates clause with a list of variables Vars.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
void Deallocate(void *Ptr) const
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return a non-unique reference to the type for a variable array of the specified element type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Expr * getBase()
Get base of the array section.
Expr * getLength()
Get length of array section.
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Expr * getLowerBound()
Get lower bound of array section.
SourceLocation getColonLocFirst() const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
Represents an attribute applied to a statement.
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
SourceLocation getBeginLoc() const
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isRelationalOp(Opcode Opc)
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
static Opcode getOpForCompoundAssignment(Opcode Opc)
SourceLocation getOperatorLoc() const
SourceLocation getExprLoc() const
static Opcode reverseComparisonOp(Opcode Opc)
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
BinaryOperatorKind Opcode
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Represents a C++ constructor within a class.
Represents a C++ conversion function within a class.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Represents a C++ struct/union/class.
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
bool hasDefinition() const
Represents a C++ nested-name-specifier or a global scope specifier.
bool isValid() const
A scope specifier is present, and it refers to a real scope.
SourceLocation getBeginLoc() const
bool isSet() const
Deprecated.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
bool isInvalid() const
An error occurred during parsing of the scope specifier.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
A wrapper class around a pointer that always points to its canonical declaration.
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getNumParams() const
void setNothrow(bool Nothrow=true)
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
SourceRange getSourceRange() const LLVM_READONLY
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
SourceLocation getBeginLoc() const LLVM_READONLY
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Declaration of a class template.
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
SourceLocation getBeginLoc() const
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
ConditionalOperator - The ?
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
bool isFileContext() const
DeclContextLookupResult lookup_result
ASTContext & getParentASTContext() const
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context semantically encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
bool isSingleDecl() const
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const
SourceLocation getLocation() const
ConstexprSpecKind getConstexprSpecifier() const
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getEndLoc() const
const DeclGroupRef getDeclGroup() const
const Decl * getSingleDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
bool isReferenced() const
Whether any declaration of this entity was referenced.
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
bool isInvalidDecl() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
void setAccess(AccessSpecifier AS)
SourceLocation getLocation() const
void setImplicit(bool I=true)
void setReferenced(bool R=true)
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
void setLexicalDeclContext(DeclContext *DC)
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
SourceLocation getIdentifierLoc() const
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
SourceLocation getBeginLoc() const LLVM_READONLY
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
bool isInvalidType() const
const IdentifierInfo * getIdentifier() const
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
RAII object that enters a new expression evaluation context.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isIntegerConstantExpr(const ASTContext &Ctx) const
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
bool isMutable() const
Determines whether this field is mutable (C++ only).
bool isBitField() const
Determines whether this field is a bitfield.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
ArrayRef< ParmVarDecl * > parameters() const
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Represents a prototype with parameter type info, e.g.
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, SourceLocation RPL, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)
Create an IfStmt.
SourceLocation getBeginLoc() const
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeTemporary(QualType Type)
Create the initialization entity for a temporary.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A class for iterating through a result set and possibly filtering out results.
Represents the results of name lookup.
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
DeclClass * getAsSingle() const
bool empty() const
Return true if no decls were found.
Filter makeFilter()
Create a filter for this result set.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
SourceLocation getExprLoc() const LLVM_READONLY
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
void setDeclName(DeclarationName N)
Set the name of this declaration.
A C++ nested-name-specifier augmented with source location information.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the 'pragma omp ...' directive.
Expr * getBase()
Fetches base expression of array shaping expression.
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Pseudo declaration for capturing expressions.
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'schedule',...
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
SourceLocation getEndLoc() const
Returns the ending location of the clause.
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
This represents 'collapse' clause in the 'pragma omp ...' directive.
static OMPCountsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Counts, std::optional< unsigned > FillIdx, SourceLocation FillLoc)
Build a 'counts' AST node.
This represents 'pragma omp declare mapper ...' directive.
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents 'pragma omp declare reduction ...' directive.
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the 'pragma omp ...' directive.
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
This represents 'pragma omp groupprivate ...' directive.
static OMPGroupPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'if' clause in the 'pragma omp ...' directive.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
static OMPLoopRangeClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc, Expr *First, Expr *Count)
Build a 'looprange' clause AST node.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This class represents the 'permutation' clause in the 'pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
This represents 'pragma omp threadprivate ...' directive.
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threadset' clause in the 'pragma omp task ...' directive.
void * getAsOpaquePtr() const
static OpaquePtr make(DeclGroupRef P)
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Represents a parameter to a function.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
ParsedAttr - Represents a syntactic attribute.
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool hasQualifiers() const
Determine whether this type has any qualifiers.
QualType withRestrict() const
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType withConst() const
void addConst()
Add the const type qualifier to this QualType.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
bool isConstant(const ASTContext &Ctx) const
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool isMoreQualifiedThan(QualType Other, const ASTContext &Ctx) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
const Type * getTypePtrOrNull() const
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
const Scope * getParent() const
getParent - Return the scope that this is nested in.
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
A generic diagnostic builder for errors which may or may not be deferred.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of 'pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
OMPClause * ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'threadset' clause.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPSplitDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp split' after parsing of its associated statement.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a 'pragma omp end declare target' was enc...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of 'pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPCountsClause(ArrayRef< Expr * > CountExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, std::optional< unsigned > FillIdx, SourceLocation FillLoc, unsigned FillCount)
Called on well-formed 'counts' clause after parsing its arguments.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the 'pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed 'pragma omp requires'.
OMPGroupPrivateDecl * CheckOMPGroupPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPGroupPrivateDecl and checks its correctness.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< Expr * > AdjustArgsNeedDeviceAddr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPLoopRangeClause(Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc)
Called on well-form 'looprange' clause after parsing its arguments.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
StmtResult ActOnOpenMPFuseDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp fuse' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the 'pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed 'pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed 'pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of 'pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
DeclGroupPtrTy ActOnOpenMPGroupPrivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp groupprivate'.
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'task_reduction' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc, Expr *Condition)
Called on well-formed 'nowait' clause.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
StmtResult ActOnOpenMPStripeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. 'pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp interchange' after parsing of its clauses and the associated statem...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
void setOpenMPDeviceNumID(StringRef ID)
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
int getOpenMPDeviceNum() const
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, OpenMPNumTeamsClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPTransparentClause(Expr *Transparent, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'transparent' clause.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, Expr *IteratorModifier, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' clause.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPDynGroupprivateClause(OpenMPDynGroupprivateClauseModifier M1, OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation EndLoc)
Called on a well-formed 'dyn_groupprivate' clause.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, Expr *IteratorModifier, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'to' clause.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'reduction' clause.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind M, SourceLocation MLoc, OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp tile' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed 'pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. 'pragma omp end declare target'.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called for 'pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Abstract base class used for diagnosing integer constant expression violations.
Sema - This implements semantic analysis and AST building for C.
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false) const
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
@ LookupAnyName
Look up any declaration with any name.
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
FPOptionsOverride CurFPFeatureOverrides()
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
ASTContext & getASTContext() const
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt)
Try to capture the given variable.
void PopExpressionEvaluationContext()
llvm::SmallSetVector< CXXRecordDecl *, 16 > AssociatedClassSet
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef< Expr * > Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses)
Find the associated classes and namespaces for argument-dependent lookup for a call with the given se...
const LangOptions & getLangOpts() const
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)
Checks access for a hierarchy conversion.
const LangOptions & LangOpts
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
DeclContext * getCurLexicalContext() const
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
ExprResult DefaultLvalueConversion(Expr *E)
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, CXXRecordDecl *Base, CXXBasePaths &Paths)
Determine whether the type Derived is a C++ class that is derived from the type Base.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
void setFunctionHasBranchProtectedScope()
std::pair< StringRef, QualType > CapturedParamNameType
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
FullExprArg MakeFullExpr(Expr *Arg)
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
void Visit(PTR(Stmt) S, ParamTys... P)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool isTLSSupported() const
Whether the target supports thread-local storage.
Represents a declaration of a type.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
bool isArithmeticType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isScalarType() const
bool isVariableArrayType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isFunctionProtoType() const
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
bool isFunctionType() const
bool isStructureOrClassType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool isFunctionNoProtoType() const
Represents the declaration of a typedef-name via the 'typedef' type specifier.
Base class for declarations which introduce a typedef-name.
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
Expr * getSubExpr() const
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
void setType(QualType newType)
VarDecl * getPotentiallyDecomposedVarDecl()
const Expr * getExprStmt() const
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
void setInitStyle(InitializationStyle Style)
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
@ CallInit
Call-style initialization (C++98)
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Retains information about a captured region.
unsigned short OpenMPLevel
unsigned short OpenMPCaptureLevel
Retains information about a function, method, or block that is currently being parsed.
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Defines the clang::TargetInfo interface.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
@ OMPC_DEFAULT_VC_unknown
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
@ Comparison
A comparison.
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Expr * AssertSuccess(ExprResult R)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ LCK_This
Capturing the *this object by reference.
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Seq
'seq' clause, allowed on 'loop' and 'routine' directives.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
ActionResult< Decl * > DeclResult
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
OpenMPNumTeamsClauseModifier
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
OpenMPDynGroupprivateClauseFallbackModifier
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
MutableArrayRef< Expr * > MultiExprArg
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
ActionResult< ParsedType > TypeResult
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
bool isOpenMPCanonicalLoopNestTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPNumTasksClauseModifier
OpenMPUseDevicePtrFallbackModifier
OpenMP 6.1 use_device_ptr fallback modifier.
@ OMPC_USE_DEVICE_PTR_FALLBACK_unknown
bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
OpenMPDynGroupprivateClauseModifier
@ OMPC_DYN_GROUPPRIVATE_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
SmallVector< CXXBaseSpecifier *, 4 > CXXCastPath
A simple array of base specifiers.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
U cast(CodeGen::Address addr)
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ None
No keyword precedes the qualified type name.
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
ActionResult< Expr * > ExprResult
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
ActionResult< Stmt * > StmtResult
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
int const char * function
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Clang specific specialization of the OMPContext to lookup target features.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
Extra information about a function prototype.
llvm::SmallVector< OMPInteropPref, 4 > Prefs
One entry of a prefer_type list.
llvm::SmallVector< Expr *, 2 > Attrs
Iterator definition representation.
SourceLocation AssignmentLoc
SourceLocation SecondColonLoc
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Expr * Upper
Normalized upper bound.
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
VarDecl * CounterVD
Internal normalized counter.
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
std::optional< Expr * > Indirect
The directive with indirect clause.
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
SourceLocation Loc
The directive location.
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Data structure for iterator expression.
int OriginalSharingModifier
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * Allocator
Allocator.