41#include "llvm/ADT/IndexedMap.h"
42#include "llvm/ADT/PointerEmbeddedInt.h"
43#include "llvm/ADT/STLExtras.h"
44#include "llvm/ADT/Sequence.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"
54using namespace llvm::omp;
67enum DefaultDataSharingAttributes {
72 DSA_firstprivate = 1 << 3,
82 unsigned Modifier = 0;
83 const Expr *RefExpr =
nullptr;
86 bool AppliedToPointee =
false;
87 DSAVarData() =
default;
91 bool AppliedToPointee)
92 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
93 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
94 AppliedToPointee(AppliedToPointee) {}
96 using OperatorOffsetTy =
98 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
100 enum class UsesAllocatorsDeclKind {
104 UserDefinedAllocator,
112 unsigned Modifier = 0;
115 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
119 bool AppliedToPointee =
false;
121 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
122 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
123 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
124 using LoopControlVariablesMapTy =
125 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
128 struct MappedExprComponentTy {
132 using MappedExprComponentsTy =
133 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
134 using CriticalsWithHintsTy =
135 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
136 struct ReductionData {
137 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
139 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
140 ReductionData() =
default;
147 ReductionOp = RefExpr;
150 using DeclReductionMapTy =
151 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
152 struct DefaultmapInfo {
156 DefaultmapInfo() =
default;
158 : ImplicitBehavior(M), SLoc(
Loc) {}
161 struct SharingMapTy {
162 DeclSAMapTy SharingMap;
163 DeclReductionMapTy ReductionMap;
164 UsedRefMapTy AlignedMap;
165 UsedRefMapTy NontemporalMap;
166 MappedExprComponentsTy MappedExprComponents;
167 LoopControlVariablesMapTy LCVMap;
168 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
173 Scope *CurScope =
nullptr;
179 DoacrossClauseMapTy DoacrossDepends;
183 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
184 bool RegionHasOrderConcurrent =
false;
185 unsigned AssociatedLoops = 1;
186 bool HasMutipleLoops =
false;
187 const Decl *PossiblyLoopCounter =
nullptr;
188 bool NowaitRegion =
false;
189 bool UntiedRegion =
false;
190 bool CancelRegion =
false;
191 bool LoopStart =
false;
192 bool BodyComplete =
false;
197 Expr *TaskgroupReductionRef =
nullptr;
198 llvm::DenseSet<QualType> MappedClassesQualTypes;
200 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
205 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
206 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
210 struct ImplicitDefaultFDInfoTy {
214 size_t StackLevel = 0;
217 ImplicitDefaultFDInfoTy(
const FieldDecl *FD,
size_t StackLevel,
219 : FD(FD), StackLevel(StackLevel), VD(VD) {}
223 ImplicitDefaultFirstprivateFDs;
224 Expr *DeclareMapperVar =
nullptr;
228 :
Directive(DKind), DirectiveName(Name), CurScope(CurScope),
230 SharingMapTy() =
default;
236 DeclSAMapTy Threadprivates;
243 bool ForceCapturing =
false;
246 bool ForceCaptureByReferenceInTargetExecutable =
false;
247 CriticalsWithHintsTy Criticals;
248 unsigned IgnoredStackElements = 0;
252 using const_iterator = StackTy::const_reverse_iterator;
253 const_iterator begin()
const {
254 return Stack.empty() ? const_iterator()
255 : Stack.back().first.rbegin() + IgnoredStackElements;
257 const_iterator end()
const {
258 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
260 using iterator = StackTy::reverse_iterator;
262 return Stack.empty() ? iterator()
263 : Stack.back().first.rbegin() + IgnoredStackElements;
266 return Stack.empty() ? iterator() : Stack.back().first.rend();
271 bool isStackEmpty()
const {
272 return Stack.empty() ||
273 Stack.back().second != CurrentNonCapturingFunctionScope ||
274 Stack.back().first.size() <= IgnoredStackElements;
276 size_t getStackSize()
const {
277 return isStackEmpty() ? 0
278 : Stack.back().first.size() - IgnoredStackElements;
281 SharingMapTy *getTopOfStackOrNull() {
282 size_t Size = getStackSize();
285 return &Stack.back().first[
Size - 1];
287 const SharingMapTy *getTopOfStackOrNull()
const {
288 return const_cast<DSAStackTy &
>(*this).getTopOfStackOrNull();
290 SharingMapTy &getTopOfStack() {
291 assert(!isStackEmpty() &&
"no current directive");
292 return *getTopOfStackOrNull();
294 const SharingMapTy &getTopOfStack()
const {
295 return const_cast<DSAStackTy &
>(*this).getTopOfStack();
298 SharingMapTy *getSecondOnStackOrNull() {
299 size_t Size = getStackSize();
302 return &Stack.back().first[
Size - 2];
304 const SharingMapTy *getSecondOnStackOrNull()
const {
305 return const_cast<DSAStackTy &
>(*this).getSecondOnStackOrNull();
314 SharingMapTy &getStackElemAtLevel(
unsigned Level) {
315 assert(Level < getStackSize() &&
"no such stack element");
316 return Stack.back().first[
Level];
318 const SharingMapTy &getStackElemAtLevel(
unsigned Level)
const {
319 return const_cast<DSAStackTy &
>(*this).getStackElemAtLevel(Level);
325 bool isOpenMPLocal(
VarDecl *
D, const_iterator
Iter)
const;
338 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
347 explicit DSAStackTy(
Sema &S) : SemaRef(S) {}
350 void setOMPAllocatorHandleT(
QualType Ty) { OMPAllocatorHandleT = Ty; }
352 QualType getOMPAllocatorHandleT()
const {
return OMPAllocatorHandleT; }
354 void setOMPAlloctraitT(
QualType Ty) { OMPAlloctraitT = Ty; }
356 QualType getOMPAlloctraitT()
const {
return OMPAlloctraitT; }
358 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
360 OMPPredefinedAllocators[AllocatorKind] = Allocator;
363 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind)
const {
364 return OMPPredefinedAllocators[AllocatorKind];
367 void setOMPDependT(
QualType Ty) { OMPDependT = Ty; }
369 QualType getOMPDependT()
const {
return OMPDependT; }
372 void setOMPEventHandleT(
QualType Ty) { OMPEventHandleT = Ty; }
374 QualType getOMPEventHandleT()
const {
return OMPEventHandleT; }
376 bool isClauseParsingMode()
const {
return ClauseKindMode != OMPC_unknown; }
378 assert(isClauseParsingMode() &&
"Must be in clause parsing mode.");
379 return ClauseKindMode;
383 bool isBodyComplete()
const {
384 const SharingMapTy *Top = getTopOfStackOrNull();
385 return Top && Top->BodyComplete;
387 void setBodyComplete() { getTopOfStack().BodyComplete =
true; }
389 bool isForceVarCapturing()
const {
return ForceCapturing; }
390 void setForceVarCapturing(
bool V) { ForceCapturing =
V; }
392 void setForceCaptureByReferenceInTargetExecutable(
bool V) {
393 ForceCaptureByReferenceInTargetExecutable =
V;
395 bool isForceCaptureByReferenceInTargetExecutable()
const {
396 return ForceCaptureByReferenceInTargetExecutable;
401 assert(!IgnoredStackElements &&
402 "cannot change stack while ignoring elements");
404 Stack.back().second != CurrentNonCapturingFunctionScope)
405 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
406 Stack.back().first.emplace_back(DKind, DirName, CurScope,
Loc);
407 Stack.back().first.back().DefaultAttrLoc =
Loc;
411 assert(!IgnoredStackElements &&
412 "cannot change stack while ignoring elements");
413 assert(!Stack.back().first.empty() &&
414 "Data-sharing attributes stack is empty!");
415 Stack.back().first.pop_back();
420 class ParentDirectiveScope {
425 ParentDirectiveScope(DSAStackTy &Self,
bool Activate)
426 : Self(Self), Active(
false) {
430 ~ParentDirectiveScope() { disable(); }
433 --Self.IgnoredStackElements;
439 ++Self.IgnoredStackElements;
448 "Expected loop-based directive.");
449 getTopOfStack().LoopStart =
true;
454 "Expected loop-based directive.");
455 getTopOfStack().LoopStart =
false;
458 bool isLoopStarted()
const {
460 "Expected loop-based directive.");
461 return !getTopOfStack().LoopStart;
464 void resetPossibleLoopCounter(
const Decl *
D =
nullptr) {
468 const Decl *getPossiblyLoopCounter()
const {
469 return getTopOfStack().PossiblyLoopCounter;
472 void pushFunction() {
473 assert(!IgnoredStackElements &&
474 "cannot change stack while ignoring elements");
476 assert(!isa<CapturingScopeInfo>(CurFnScope));
477 CurrentNonCapturingFunctionScope = CurFnScope;
481 assert(!IgnoredStackElements &&
482 "cannot change stack while ignoring elements");
483 if (!Stack.empty() && Stack.back().second == OldFSI) {
484 assert(Stack.back().first.empty());
487 CurrentNonCapturingFunctionScope =
nullptr;
489 if (!isa<CapturingScopeInfo>(FSI)) {
490 CurrentNonCapturingFunctionScope = FSI;
497 Criticals.try_emplace(
D->getDirectiveName().getAsString(),
D, Hint);
499 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
501 auto I = Criticals.find(Name.getAsString());
502 if (I != Criticals.end())
504 return std::make_pair(
nullptr, llvm::APSInt());
521 const LCDeclInfo isLoopControlVariable(
const ValueDecl *
D)
const;
526 const LCDeclInfo isParentLoopControlVariable(
const ValueDecl *
D)
const;
531 const LCDeclInfo isLoopControlVariable(
const ValueDecl *
D,
532 unsigned Level)
const;
535 const ValueDecl *getParentLoopControlVariable(
unsigned I)
const;
538 void markDeclAsUsedInScanDirective(
ValueDecl *
D) {
539 if (SharingMapTy *Stack = getSecondOnStackOrNull())
540 Stack->UsedInScanDirective.insert(
D);
544 bool isUsedInScanDirective(
ValueDecl *
D)
const {
545 if (
const SharingMapTy *Stack = getTopOfStackOrNull())
546 return Stack->UsedInScanDirective.contains(
D);
552 DeclRefExpr *PrivateCopy =
nullptr,
unsigned Modifier = 0,
553 bool AppliedToPointee =
false);
562 const Expr *ReductionRef);
568 Expr *&TaskgroupDescriptor)
const;
573 const Expr *&ReductionRef,
574 Expr *&TaskgroupDescriptor)
const;
577 Expr *getTaskgroupReductionRef()
const {
578 assert((getTopOfStack().
Directive == OMPD_taskgroup ||
582 "taskgroup reference expression requested for non taskgroup or "
583 "parallel/worksharing directive.");
584 return getTopOfStack().TaskgroupReductionRef;
588 bool isTaskgroupReductionRef(
const ValueDecl *VD,
unsigned Level)
const {
589 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
590 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
596 const DSAVarData getTopDSA(
ValueDecl *
D,
bool FromParent);
598 const DSAVarData getImplicitDSA(
ValueDecl *
D,
bool FromParent)
const;
600 const DSAVarData getImplicitDSA(
ValueDecl *
D,
unsigned Level)
const;
607 DefaultDataSharingAttributes)>
610 bool FromParent)
const;
618 bool FromParent)
const;
625 unsigned Level,
bool NotLastprivate =
false)
const;
629 bool hasExplicitDirective(
631 unsigned Level)
const;
635 const llvm::function_ref<
bool(
638 bool FromParent)
const;
642 const SharingMapTy *Top = getTopOfStackOrNull();
643 return Top ? Top->Directive : OMPD_unknown;
647 assert(!isStackEmpty() &&
"No directive at specified level.");
648 return getStackElemAtLevel(Level).Directive;
652 unsigned OpenMPCaptureLevel)
const {
655 return CaptureRegions[OpenMPCaptureLevel];
659 const SharingMapTy *
Parent = getSecondOnStackOrNull();
664 void addRequiresDecl(
OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
667 template <
typename ClauseType>
bool hasRequiresDeclWithClause()
const {
669 return llvm::any_of(
D->clauselists(), [](
const OMPClause *
C) {
670 return isa<ClauseType>(C);
678 bool IsDuplicate =
false;
681 for (
const OMPClause *CPrev :
D->clauselists()) {
682 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
683 SemaRef.
Diag(CNew->getBeginLoc(),
684 diag::err_omp_requires_clause_redeclaration)
685 << getOpenMPClauseName(CNew->getClauseKind());
686 SemaRef.
Diag(CPrev->getBeginLoc(),
687 diag::note_omp_requires_previous_clause)
688 << getOpenMPClauseName(CPrev->getClauseKind());
699 TargetLocations.push_back(LocStart);
705 AtomicLocation =
Loc;
710 SourceLocation getAtomicDirectiveLoc()
const {
return AtomicLocation; }
714 return TargetLocations;
719 getTopOfStack().DefaultAttr = DSA_none;
720 getTopOfStack().DefaultAttrLoc =
Loc;
724 getTopOfStack().DefaultAttr = DSA_shared;
725 getTopOfStack().DefaultAttrLoc =
Loc;
729 getTopOfStack().DefaultAttr = DSA_private;
730 getTopOfStack().DefaultAttrLoc =
Loc;
734 getTopOfStack().DefaultAttr = DSA_firstprivate;
735 getTopOfStack().DefaultAttrLoc =
Loc;
740 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[
Kind];
741 DMI.ImplicitBehavior = M;
747 return getTopOfStack()
748 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
751 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
754 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
756 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
761 return ConstructTraits;
766 ConstructTraits.append(Traits.begin(), Traits.end());
768 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
769 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
770 assert(Top == Trait &&
"Something left a trait on the stack!");
776 DefaultDataSharingAttributes getDefaultDSA(
unsigned Level)
const {
777 return getStackSize() <=
Level ? DSA_unspecified
778 : getStackElemAtLevel(Level).DefaultAttr;
780 DefaultDataSharingAttributes getDefaultDSA()
const {
781 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
784 return isStackEmpty() ?
SourceLocation() : getTopOfStack().DefaultAttrLoc;
788 return isStackEmpty()
790 : getTopOfStack().DefaultmapMap[
Kind].ImplicitBehavior;
793 getDefaultmapModifierAtLevel(
unsigned Level,
795 return getStackElemAtLevel(Level).DefaultmapMap[
Kind].ImplicitBehavior;
797 bool isDefaultmapCapturedByRef(
unsigned Level,
800 getDefaultmapModifierAtLevel(Level, Kind);
801 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
802 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
806 (M == OMPC_DEFAULTMAP_MODIFIER_present);
813 case OMPC_DEFAULTMAP_scalar:
814 case OMPC_DEFAULTMAP_pointer:
816 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
817 (M == OMPC_DEFAULTMAP_MODIFIER_default);
818 case OMPC_DEFAULTMAP_aggregate:
819 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
823 llvm_unreachable(
"Unexpected OpenMPDefaultmapClauseKind enum");
825 bool mustBeFirstprivateAtLevel(
unsigned Level,
828 getDefaultmapModifierAtLevel(Level, Kind);
829 return mustBeFirstprivateBase(M, Kind);
833 return mustBeFirstprivateBase(M, Kind);
838 const DSAVarData DVar = getTopDSA(
D,
false);
843 void setOrderedRegion(
bool IsOrdered,
const Expr *Param,
846 getTopOfStack().OrderedRegion.emplace(Param, Clause);
848 getTopOfStack().OrderedRegion.reset();
852 bool isOrderedRegion()
const {
853 if (
const SharingMapTy *Top = getTopOfStackOrNull())
854 return Top->OrderedRegion.has_value();
858 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam()
const {
859 if (
const SharingMapTy *Top = getTopOfStackOrNull())
860 if (Top->OrderedRegion)
861 return *Top->OrderedRegion;
862 return std::make_pair(
nullptr,
nullptr);
866 bool isParentOrderedRegion()
const {
867 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
868 return Parent->OrderedRegion.has_value();
872 std::pair<const Expr *, OMPOrderedClause *>
873 getParentOrderedRegionParam()
const {
874 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
875 if (
Parent->OrderedRegion)
876 return *
Parent->OrderedRegion;
877 return std::make_pair(
nullptr,
nullptr);
880 void setRegionHasOrderConcurrent(
bool HasOrderConcurrent) {
881 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
885 bool isParentOrderConcurrent()
const {
886 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
887 return Parent->RegionHasOrderConcurrent;
891 void setNowaitRegion(
bool IsNowait =
true) {
892 getTopOfStack().NowaitRegion = IsNowait;
896 bool isParentNowaitRegion()
const {
897 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
898 return Parent->NowaitRegion;
902 void setUntiedRegion(
bool IsUntied =
true) {
903 getTopOfStack().UntiedRegion = IsUntied;
906 bool isUntiedRegion()
const {
907 const SharingMapTy *Top = getTopOfStackOrNull();
908 return Top ? Top->UntiedRegion :
false;
911 void setParentCancelRegion(
bool Cancel =
true) {
912 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
913 Parent->CancelRegion |= Cancel;
916 bool isCancelRegion()
const {
917 const SharingMapTy *Top = getTopOfStackOrNull();
918 return Top ? Top->CancelRegion :
false;
923 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
927 bool doesParentHasScanDirective()
const {
928 const SharingMapTy *Top = getSecondOnStackOrNull();
929 return Top ? Top->PrevScanLocation.isValid() :
false;
933 const SharingMapTy *Top = getSecondOnStackOrNull();
938 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
942 bool doesParentHasOrderedDirective()
const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevOrderedLocation.isValid() :
false;
948 const SharingMapTy *Top = getSecondOnStackOrNull();
953 void setAssociatedLoops(
unsigned Val) {
954 getTopOfStack().AssociatedLoops = Val;
956 getTopOfStack().HasMutipleLoops =
true;
959 unsigned getAssociatedLoops()
const {
960 const SharingMapTy *Top = getTopOfStackOrNull();
961 return Top ? Top->AssociatedLoops : 0;
964 bool hasMutipleLoops()
const {
965 const SharingMapTy *Top = getTopOfStackOrNull();
966 return Top ? Top->HasMutipleLoops :
false;
972 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
973 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
976 bool hasInnerTeamsRegion()
const {
977 return getInnerTeamsRegionLoc().
isValid();
981 const SharingMapTy *Top = getTopOfStackOrNull();
985 Scope *getCurScope()
const {
986 const SharingMapTy *Top = getTopOfStackOrNull();
987 return Top ? Top->CurScope :
nullptr;
989 void setContext(
DeclContext *DC) { getTopOfStack().Context = DC; }
991 const SharingMapTy *Top = getTopOfStackOrNull();
997 bool checkMappableExprComponentListsForDecl(
998 const ValueDecl *VD,
bool CurrentRegionOnly,
999 const llvm::function_ref<
1011 if (CurrentRegionOnly)
1014 std::advance(SI, 1);
1016 for (; SI != SE; ++SI) {
1017 auto MI = SI->MappedExprComponents.find(VD);
1018 if (MI != SI->MappedExprComponents.end())
1020 MI->second.Components)
1021 if (Check(L, MI->second.Kind))
1029 bool checkMappableExprComponentListsForDeclAtLevel(
1031 const llvm::function_ref<
1035 if (getStackSize() <= Level)
1038 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1039 auto MI = StackElem.MappedExprComponents.find(VD);
1040 if (MI != StackElem.MappedExprComponents.end())
1042 MI->second.Components)
1043 if (Check(L, MI->second.Kind))
1050 void addMappableExpressionComponents(
1054 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1056 MEC.Components.resize(MEC.Components.size() + 1);
1057 MEC.Components.back().append(Components.begin(), Components.end());
1058 MEC.Kind = WhereFoundClauseKind;
1061 unsigned getNestingLevel()
const {
1062 assert(!isStackEmpty());
1063 return getStackSize() - 1;
1065 void addDoacrossDependClause(
OMPClause *
C,
const OperatorOffsetTy &OpsOffs) {
1066 SharingMapTy *
Parent = getSecondOnStackOrNull();
1068 Parent->DoacrossDepends.try_emplace(
C, OpsOffs);
1070 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1071 getDoacrossDependClauses()
const {
1072 const SharingMapTy &StackElem = getTopOfStack();
1074 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1075 return llvm::make_range(Ref.begin(), Ref.end());
1077 return llvm::make_range(StackElem.DoacrossDepends.end(),
1078 StackElem.DoacrossDepends.end());
1082 void addMappedClassesQualTypes(
QualType QT) {
1083 SharingMapTy &StackElem = getTopOfStack();
1084 StackElem.MappedClassesQualTypes.insert(QT);
1088 bool isClassPreviouslyMapped(
QualType QT)
const {
1089 const SharingMapTy &StackElem = getTopOfStack();
1090 return StackElem.MappedClassesQualTypes.contains(QT);
1094 void addToParentTargetRegionLinkGlobals(
DeclRefExpr *
E) {
1095 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1096 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1097 "Expected declare target link global.");
1098 for (
auto &Elem : *
this) {
1100 Elem.DeclareTargetLinkVarDecls.push_back(
E);
1110 "Expected target executable directive.");
1111 return getTopOfStack().DeclareTargetLinkVarDecls;
1115 void addInnerAllocatorExpr(
Expr *
E) {
1116 getTopOfStack().InnerUsedAllocators.push_back(
E);
1120 return getTopOfStack().InnerUsedAllocators;
1124 void addImplicitTaskFirstprivate(
unsigned Level,
Decl *
D) {
1125 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(
D);
1128 bool isImplicitTaskFirstprivate(
Decl *
D)
const {
1129 return getTopOfStack().ImplicitTaskFirstprivates.contains(
D);
1133 void addUsesAllocatorsDecl(
const Decl *
D, UsesAllocatorsDeclKind Kind) {
1134 getTopOfStack().UsesAllocatorsDecls.try_emplace(
D, Kind);
1138 std::optional<UsesAllocatorsDeclKind>
1139 isUsesAllocatorsDecl(
unsigned Level,
const Decl *
D)
const {
1140 const SharingMapTy &StackElem = getTopOfStack();
1141 auto I = StackElem.UsesAllocatorsDecls.find(
D);
1142 if (I == StackElem.UsesAllocatorsDecls.end())
1143 return std::nullopt;
1144 return I->getSecond();
1146 std::optional<UsesAllocatorsDeclKind>
1147 isUsesAllocatorsDecl(
const Decl *
D)
const {
1148 const SharingMapTy &StackElem = getTopOfStack();
1149 auto I = StackElem.UsesAllocatorsDecls.find(
D);
1150 if (I == StackElem.UsesAllocatorsDecls.end())
1151 return std::nullopt;
1152 return I->getSecond();
1155 void addDeclareMapperVarRef(
Expr *Ref) {
1156 SharingMapTy &StackElem = getTopOfStack();
1157 StackElem.DeclareMapperVar = Ref;
1159 const Expr *getDeclareMapperVarRef()
const {
1160 const SharingMapTy *Top = getTopOfStackOrNull();
1161 return Top ? Top->DeclareMapperVar :
nullptr;
1165 void addIteratorVarDecl(
VarDecl *VD) {
1166 SharingMapTy &StackElem = getTopOfStack();
1170 bool isIteratorVarDecl(
const VarDecl *VD)
const {
1171 const SharingMapTy *Top = getTopOfStackOrNull();
1179 const_iterator I = begin();
1180 const_iterator EndI = end();
1181 size_t StackLevel = getStackSize();
1182 for (; I != EndI; ++I) {
1183 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1187 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1190 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1191 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1196 bool isImplicitDefaultFirstprivateFD(
VarDecl *VD)
const {
1197 const_iterator I = begin();
1198 const_iterator EndI = end();
1199 for (; I != EndI; ++I)
1200 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1204 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1211 iterator I = begin();
1212 const_iterator EndI = end();
1213 size_t StackLevel = getStackSize();
1214 for (; I != EndI; ++I) {
1215 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1216 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1221 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1231 DKind == OMPD_unknown;
1237 if (
const auto *FE = dyn_cast<FullExpr>(
E))
1238 E = FE->getSubExpr();
1240 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
E))
1241 E = MTE->getSubExpr();
1243 while (
const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(
E))
1244 E = Binder->getSubExpr();
1246 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(
E))
1247 E = ICE->getSubExprAsWritten();
1256 if (
const auto *CED = dyn_cast<OMPCapturedExprDecl>(
D))
1257 if (
const auto *ME = dyn_cast<MemberExpr>(
getExprAsWritten(CED->getInit())))
1258 D = ME->getMemberDecl();
1269DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &
Iter,
1272 auto *VD = dyn_cast<VarDecl>(
D);
1273 const auto *FD = dyn_cast<FieldDecl>(
D);
1275 if (
Iter == end()) {
1282 DVar.CKind = OMPC_shared;
1289 DVar.CKind = OMPC_shared;
1293 DVar.CKind = OMPC_shared;
1304 DVar.CKind = OMPC_private;
1308 DVar.DKind =
Iter->Directive;
1311 if (
Iter->SharingMap.count(
D)) {
1312 const DSAInfo &
Data =
Iter->SharingMap.lookup(
D);
1313 DVar.RefExpr =
Data.RefExpr.getPointer();
1314 DVar.PrivateCopy =
Data.PrivateCopy;
1315 DVar.CKind =
Data.Attributes;
1316 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1317 DVar.Modifier =
Data.Modifier;
1318 DVar.AppliedToPointee =
Data.AppliedToPointee;
1326 switch (
Iter->DefaultAttr) {
1328 DVar.CKind = OMPC_shared;
1329 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1333 case DSA_firstprivate:
1336 DVar.CKind = OMPC_unknown;
1338 DVar.CKind = OMPC_firstprivate;
1340 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1348 DVar.CKind = OMPC_unknown;
1350 DVar.CKind = OMPC_private;
1352 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1354 case DSA_unspecified:
1359 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1363 DVar.CKind = OMPC_shared;
1373 DSAVarData DVarTemp;
1374 const_iterator I =
Iter,
E = end();
1382 DVarTemp = getDSA(I,
D);
1383 if (DVarTemp.CKind != OMPC_shared) {
1384 DVar.RefExpr =
nullptr;
1385 DVar.CKind = OMPC_firstprivate;
1388 }
while (I !=
E && !isImplicitTaskingRegion(I->Directive));
1390 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1399 return getDSA(++
Iter,
D);
1403 const Expr *NewDE) {
1404 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1406 SharingMapTy &StackElem = getTopOfStack();
1407 auto It = StackElem.AlignedMap.find(
D);
1408 if (It == StackElem.AlignedMap.end()) {
1409 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1410 StackElem.AlignedMap[
D] = NewDE;
1413 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1418 const Expr *NewDE) {
1419 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1421 SharingMapTy &StackElem = getTopOfStack();
1422 auto It = StackElem.NontemporalMap.find(
D);
1423 if (It == StackElem.NontemporalMap.end()) {
1424 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1425 StackElem.NontemporalMap[
D] = NewDE;
1428 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1433 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1435 SharingMapTy &StackElem = getTopOfStack();
1436 StackElem.LCVMap.try_emplace(
1437 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1440const DSAStackTy::LCDeclInfo
1441DSAStackTy::isLoopControlVariable(
const ValueDecl *
D)
const {
1442 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1444 const SharingMapTy &StackElem = getTopOfStack();
1445 auto It = StackElem.LCVMap.find(
D);
1446 if (It != StackElem.LCVMap.end())
1448 return {0,
nullptr};
1451const DSAStackTy::LCDeclInfo
1452DSAStackTy::isLoopControlVariable(
const ValueDecl *
D,
unsigned Level)
const {
1453 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1455 for (
unsigned I = Level + 1; I > 0; --I) {
1456 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1457 auto It = StackElem.LCVMap.find(
D);
1458 if (It != StackElem.LCVMap.end())
1461 return {0,
nullptr};
1464const DSAStackTy::LCDeclInfo
1465DSAStackTy::isParentLoopControlVariable(
const ValueDecl *
D)
const {
1466 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1467 assert(
Parent &&
"Data-sharing attributes stack is empty");
1469 auto It =
Parent->LCVMap.find(
D);
1470 if (It !=
Parent->LCVMap.end())
1472 return {0,
nullptr};
1475const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1476 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1477 assert(
Parent &&
"Data-sharing attributes stack is empty");
1478 if (
Parent->LCVMap.size() < I)
1480 for (
const auto &Pair :
Parent->LCVMap)
1481 if (Pair.second.first == I)
1488 bool AppliedToPointee) {
1490 if (A == OMPC_threadprivate) {
1491 DSAInfo &
Data = Threadprivates[
D];
1492 Data.Attributes = A;
1493 Data.RefExpr.setPointer(
E);
1494 Data.PrivateCopy =
nullptr;
1495 Data.Modifier = Modifier;
1497 DSAInfo &
Data = getTopOfStack().SharingMap[
D];
1498 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1499 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1500 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1501 (isLoopControlVariable(
D).first && A == OMPC_private));
1502 Data.Modifier = Modifier;
1503 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1504 Data.RefExpr.setInt(
true);
1507 const bool IsLastprivate =
1508 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1509 Data.Attributes = A;
1510 Data.RefExpr.setPointerAndInt(
E, IsLastprivate);
1511 Data.PrivateCopy = PrivateCopy;
1512 Data.AppliedToPointee = AppliedToPointee;
1514 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1515 Data.Modifier = Modifier;
1516 Data.Attributes = A;
1517 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1518 Data.PrivateCopy =
nullptr;
1519 Data.AppliedToPointee = AppliedToPointee;
1526 StringRef Name,
const AttrVec *Attrs =
nullptr,
1541 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1548 bool RefersToCapture =
false) {
1559 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1561 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1562 "Additional reduction info may be specified only for reduction items.");
1563 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1564 assert(ReductionData.ReductionRange.isInvalid() &&
1565 (getTopOfStack().
Directive == OMPD_taskgroup ||
1569 "Additional reduction info may be specified only once for reduction "
1571 ReductionData.set(BOK, SR);
1572 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1573 if (!TaskgroupReductionRef) {
1576 TaskgroupReductionRef =
1582 const Expr *ReductionRef) {
1584 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1586 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1587 "Additional reduction info may be specified only for reduction items.");
1588 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1589 assert(ReductionData.ReductionRange.isInvalid() &&
1590 (getTopOfStack().
Directive == OMPD_taskgroup ||
1594 "Additional reduction info may be specified only once for reduction "
1596 ReductionData.set(ReductionRef, SR);
1597 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1598 if (!TaskgroupReductionRef) {
1601 TaskgroupReductionRef =
1606const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1608 Expr *&TaskgroupDescriptor)
const {
1610 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1611 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1612 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1613 if (
Data.Attributes != OMPC_reduction ||
1614 Data.Modifier != OMPC_REDUCTION_task)
1616 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1617 if (!ReductionData.ReductionOp ||
1618 ReductionData.ReductionOp.is<
const Expr *>())
1619 return DSAVarData();
1620 SR = ReductionData.ReductionRange;
1621 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1622 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1623 "expression for the descriptor is not "
1625 TaskgroupDescriptor = I->TaskgroupReductionRef;
1626 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1627 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1630 return DSAVarData();
1633const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1635 Expr *&TaskgroupDescriptor)
const {
1637 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1638 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1639 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1640 if (
Data.Attributes != OMPC_reduction ||
1641 Data.Modifier != OMPC_REDUCTION_task)
1643 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1644 if (!ReductionData.ReductionOp ||
1645 !ReductionData.ReductionOp.is<
const Expr *>())
1646 return DSAVarData();
1647 SR = ReductionData.ReductionRange;
1648 ReductionRef = ReductionData.ReductionOp.get<
const Expr *>();
1649 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1650 "expression for the descriptor is not "
1652 TaskgroupDescriptor = I->TaskgroupReductionRef;
1653 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1654 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1657 return DSAVarData();
1660bool DSAStackTy::isOpenMPLocal(
VarDecl *
D, const_iterator I)
const {
1662 for (const_iterator
E = end(); I !=
E; ++I) {
1663 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1667 Scope *CurScope = getCurScope();
1668 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(
D))
1670 return CurScope != TopScope;
1673 if (I->Context == DC)
1682 bool AcceptIfMutable =
true,
1683 bool *IsClassType =
nullptr) {
1685 Type =
Type.getNonReferenceType().getCanonicalType();
1686 bool IsConstant =
Type.isConstant(Context);
1691 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1693 RD = CTD->getTemplatedDecl();
1696 return IsConstant && !(SemaRef.
getLangOpts().CPlusPlus && RD &&
1703 bool AcceptIfMutable =
true,
1704 bool ListItemNotVar =
false) {
1708 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1709 : IsClassType ? diag::err_omp_const_not_mutable_variable
1710 : diag::err_omp_const_variable;
1711 SemaRef.
Diag(ELoc,
Diag) << getOpenMPClauseName(CKind);
1712 if (!ListItemNotVar &&
D) {
1713 const VarDecl *VD = dyn_cast<VarDecl>(
D);
1717 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1725const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(
ValueDecl *
D,
1730 auto *VD = dyn_cast<VarDecl>(
D);
1731 auto TI = Threadprivates.find(
D);
1732 if (TI != Threadprivates.end()) {
1733 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1734 DVar.CKind = OMPC_threadprivate;
1735 DVar.Modifier = TI->getSecond().Modifier;
1738 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1740 SemaRef, VD,
D->getType().getNonReferenceType(),
1741 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1742 DVar.CKind = OMPC_threadprivate;
1743 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1750 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1756 SemaRef, VD,
D->getType().getNonReferenceType(),
D->
getLocation());
1757 DVar.CKind = OMPC_threadprivate;
1758 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1763 !isLoopControlVariable(
D).first) {
1764 const_iterator IterTarget =
1765 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1768 if (IterTarget != end()) {
1769 const_iterator ParentIterTarget = IterTarget + 1;
1770 for (const_iterator
Iter = begin();
Iter != ParentIterTarget; ++
Iter) {
1771 if (isOpenMPLocal(VD,
Iter)) {
1775 DVar.CKind = OMPC_threadprivate;
1779 if (!isClauseParsingMode() || IterTarget != begin()) {
1780 auto DSAIter = IterTarget->SharingMap.find(
D);
1781 if (DSAIter != IterTarget->SharingMap.end() &&
1783 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1784 DVar.CKind = OMPC_threadprivate;
1787 const_iterator End = end();
1789 D, std::distance(ParentIterTarget, End),
1793 IterTarget->ConstructLoc);
1794 DVar.CKind = OMPC_threadprivate;
1814 const_iterator I = begin();
1815 const_iterator EndI = end();
1816 if (FromParent && I != EndI)
1819 auto It = I->SharingMap.find(
D);
1820 if (It != I->SharingMap.end()) {
1821 const DSAInfo &
Data = It->getSecond();
1822 DVar.RefExpr =
Data.RefExpr.getPointer();
1823 DVar.PrivateCopy =
Data.PrivateCopy;
1824 DVar.CKind =
Data.Attributes;
1825 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1826 DVar.DKind = I->Directive;
1827 DVar.Modifier =
Data.Modifier;
1828 DVar.AppliedToPointee =
Data.AppliedToPointee;
1833 DVar.CKind = OMPC_shared;
1840 if (SemaRef.
LangOpts.OpenMP <= 31) {
1848 DSAVarData DVarTemp = hasInnermostDSA(
1851 return C == OMPC_firstprivate ||
C == OMPC_shared;
1853 MatchesAlways, FromParent);
1854 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1857 DVar.CKind = OMPC_shared;
1864 const_iterator I = begin();
1865 const_iterator EndI = end();
1866 if (FromParent && I != EndI)
1870 auto It = I->SharingMap.find(
D);
1871 if (It != I->SharingMap.end()) {
1872 const DSAInfo &
Data = It->getSecond();
1873 DVar.RefExpr =
Data.RefExpr.getPointer();
1874 DVar.PrivateCopy =
Data.PrivateCopy;
1875 DVar.CKind =
Data.Attributes;
1876 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1877 DVar.DKind = I->Directive;
1878 DVar.Modifier =
Data.Modifier;
1879 DVar.AppliedToPointee =
Data.AppliedToPointee;
1885const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1886 bool FromParent)
const {
1887 if (isStackEmpty()) {
1889 return getDSA(I,
D);
1892 const_iterator StartI = begin();
1893 const_iterator EndI = end();
1894 if (FromParent && StartI != EndI)
1896 return getDSA(StartI,
D);
1899const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1900 unsigned Level)
const {
1901 if (getStackSize() <= Level)
1902 return DSAVarData();
1904 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1905 return getDSA(StartI,
D);
1908const DSAStackTy::DSAVarData
1911 DefaultDataSharingAttributes)>
1914 bool FromParent)
const {
1918 const_iterator I = begin();
1919 const_iterator EndI = end();
1920 if (FromParent && I != EndI)
1922 for (; I != EndI; ++I) {
1923 if (!DPred(I->Directive) &&
1924 !isImplicitOrExplicitTaskingRegion(I->Directive))
1926 const_iterator NewI = I;
1927 DSAVarData DVar = getDSA(NewI,
D);
1928 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1934const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1937 bool FromParent)
const {
1941 const_iterator StartI = begin();
1942 const_iterator EndI = end();
1943 if (FromParent && StartI != EndI)
1945 if (StartI == EndI || !DPred(StartI->Directive))
1947 const_iterator NewI = StartI;
1948 DSAVarData DVar = getDSA(NewI,
D);
1949 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1954bool DSAStackTy::hasExplicitDSA(
1957 unsigned Level,
bool NotLastprivate)
const {
1958 if (getStackSize() <= Level)
1961 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1962 auto I = StackElem.SharingMap.find(
D);
1963 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1964 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1965 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1968 auto LI = StackElem.LCVMap.find(
D);
1969 if (LI != StackElem.LCVMap.end())
1970 return CPred(OMPC_private,
false);
1974bool DSAStackTy::hasExplicitDirective(
1976 unsigned Level)
const {
1977 if (getStackSize() <= Level)
1979 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1980 return DPred(StackElem.Directive);
1983bool DSAStackTy::hasDirective(
1987 bool FromParent)
const {
1989 size_t Skip = FromParent ? 2 : 1;
1990 for (const_iterator I = begin() + std::min(Skip, getStackSize()),
E = end();
1992 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1998void SemaOpenMP::InitDataSharingAttributesStack() {
1999 VarDataSharingAttributesStack =
new DSAStackTy(
SemaRef);
2002#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2004void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2012 "Expected OpenMP device compilation.");
2018enum class FunctionEmissionStatus {
2029 "Expected OpenMP device compilation.");
2031 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2036 Kind = SemaDiagnosticBuilder::K_Immediate;
2047 ? SemaDiagnosticBuilder::K_Deferred
2048 : SemaDiagnosticBuilder::K_Immediate;
2052 Kind = SemaDiagnosticBuilder::K_Nop;
2055 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2067 "Expected OpenMP host compilation.");
2069 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2074 Kind = SemaDiagnosticBuilder::K_Immediate;
2077 Kind = SemaDiagnosticBuilder::K_Deferred;
2082 Kind = SemaDiagnosticBuilder::K_Nop;
2092 if (LO.OpenMP <= 45) {
2094 return OMPC_DEFAULTMAP_scalar;
2095 return OMPC_DEFAULTMAP_aggregate;
2098 return OMPC_DEFAULTMAP_pointer;
2100 return OMPC_DEFAULTMAP_scalar;
2101 return OMPC_DEFAULTMAP_aggregate;
2105 unsigned OpenMPCaptureLevel)
const {
2106 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2109 bool IsByRef =
true;
2115 bool IsVariableUsedInMapClause =
false;
2177 bool IsVariableAssociatedWithSection =
false;
2179 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2181 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2188 if (WhereFoundClauseKind != OMPC_map &&
2189 WhereFoundClauseKind != OMPC_has_device_addr)
2192 auto EI = MapExprComponents.rbegin();
2193 auto EE = MapExprComponents.rend();
2195 assert(EI != EE &&
"Invalid map expression!");
2197 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2198 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() ==
D;
2203 auto Last = std::prev(EE);
2205 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2206 if ((UO && UO->getOpcode() == UO_Deref) ||
2207 isa<ArraySubscriptExpr>(
Last->getAssociatedExpression()) ||
2208 isa<ArraySectionExpr>(
Last->getAssociatedExpression()) ||
2209 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2210 isa<OMPArrayShapingExpr>(
Last->getAssociatedExpression())) {
2211 IsVariableAssociatedWithSection =
true;
2220 if (IsVariableUsedInMapClause) {
2223 IsByRef = !(Ty->
isPointerType() && IsVariableAssociatedWithSection);
2228 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2231 DSAStack->isDefaultmapCapturedByRef(
2236 return K == OMPC_reduction && !AppliedToPointee;
2244 ((IsVariableUsedInMapClause &&
2245 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2250 return K == OMPC_firstprivate ||
2251 (K == OMPC_reduction && AppliedToPointee);
2254 DSAStack->isUsesAllocatorsDecl(Level,
D))) &&
2257 !(isa<OMPCapturedExprDecl>(
D) && !
D->
hasAttr<OMPCaptureNoInitAttr>() &&
2258 !cast<OMPCapturedExprDecl>(
D)->getInit()->isGLValue()) &&
2261 !((
DSAStack->getDefaultDSA() == DSA_firstprivate ||
2262 DSAStack->getDefaultDSA() == DSA_private) &&
2266 !
DSAStack->isLoopControlVariable(
D, Level).first);
2283unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2285 return DSAStack->getNestingLevel();
2295 !
DSAStack->isClauseParsingMode()) ||
2306 if (!dyn_cast<FieldDecl>(
D))
2308 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2311 DefaultDataSharingAttributes DefaultAttr) {
2313 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2317 if (DVarPrivate.CKind != OMPC_unknown)
2323 Expr *CaptureExpr,
bool WithInit,
2329 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2332 auto *VD = dyn_cast<VarDecl>(
D);
2341 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2351 DSAStackTy::DSAVarData DVarTop =
2353 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2358 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2365 if (!isa<CapturingScopeInfo>(FSI))
2367 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2373 assert(CSI &&
"Failed to find CapturedRegionScopeInfo");
2384 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2390 if (CheckScopeInfo) {
2391 bool OpenMPFound =
false;
2392 for (
unsigned I = StopAt + 1; I > 0; --I) {
2394 if (!isa<CapturingScopeInfo>(FSI))
2396 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2406 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2407 (!
DSAStack->isClauseParsingMode() ||
2408 DSAStack->getParentDirective() != OMPD_unknown)) {
2409 auto &&Info =
DSAStack->isLoopControlVariable(
D);
2412 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2413 (VD &&
DSAStack->isForceVarCapturing()))
2414 return VD ? VD : Info.second;
2415 DSAStackTy::DSAVarData DVarTop =
2417 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2419 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2425 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2433 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2434 ((
DSAStack->getDefaultDSA() != DSA_none &&
2435 DSAStack->getDefaultDSA() != DSA_private &&
2436 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2437 DVarTop.CKind == OMPC_shared))
2439 auto *FD = dyn_cast<FieldDecl>(
D);
2440 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2441 !DVarPrivate.PrivateCopy) {
2442 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2445 DefaultDataSharingAttributes DefaultAttr) {
2447 (DefaultAttr == DSA_firstprivate ||
2448 DefaultAttr == DSA_private);
2452 if (DVarPrivate.CKind == OMPC_unknown)
2475 VD = cast<VarDecl>(VDPrivateRefExpr->
getDecl());
2476 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2479 if (DVarPrivate.CKind != OMPC_unknown ||
2480 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2481 DSAStack->getDefaultDSA() == DSA_private ||
2482 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2483 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2488void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2489 unsigned Level)
const {
2494 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2500 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2502 DSAStack->resetPossibleLoopCounter();
2508 unsigned CapLevel)
const {
2509 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2510 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2511 (!
DSAStack->isClauseParsingMode() ||
2512 DSAStack->getParentDirective() != OMPD_unknown)) {
2513 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2516 DefaultDataSharingAttributes DefaultAttr) {
2518 DefaultAttr == DSA_private;
2522 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(
D) &&
2523 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(
D)) &&
2524 !
DSAStack->isLoopControlVariable(
D).first)
2525 return OMPC_private;
2528 bool IsTriviallyCopyable =
2529 D->getType().getNonReferenceType().isTriviallyCopyableType(
2532 .getNonReferenceType()
2534 ->getAsCXXRecordDecl();
2539 (IsTriviallyCopyable ||
2545 return OMPC_firstprivate;
2546 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2547 if (DVar.CKind != OMPC_shared &&
2548 !
DSAStack->isLoopControlVariable(
D, Level).first && !DVar.RefExpr) {
2549 DSAStack->addImplicitTaskFirstprivate(Level,
D);
2550 return OMPC_firstprivate;
2559 return OMPC_private;
2562 DSAStack->isLoopControlVariable(
D).first) &&
2567 return OMPC_private;
2569 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2575 return OMPC_private;
2580 DSAStack->isUsesAllocatorsDecl(Level,
D).value_or(
2581 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2582 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2583 return OMPC_private;
2587 (
DSAStack->isClauseParsingMode() &&
2588 DSAStack->getClauseParsingMode() == OMPC_private) ||
2593 return K == OMPD_taskgroup ||
2594 ((isOpenMPParallelDirective(K) ||
2595 isOpenMPWorksharingDirective(K)) &&
2596 !isOpenMPSimdDirective(K));
2599 DSAStack->isTaskgroupReductionRef(
D, Level)))
2606 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2609 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2610 const unsigned NewLevel = I - 1;
2614 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2622 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2632 if (
DSAStack->mustBeFirstprivateAtLevel(
2634 OMPC = OMPC_firstprivate;
2638 if (OMPC != OMPC_unknown)
2640 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2644 unsigned CaptureLevel)
const {
2645 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2650 const auto *VD = dyn_cast<VarDecl>(
D);
2654 Regions[CaptureLevel] != OMPD_task;
2658 unsigned CaptureLevel)
const {
2659 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2662 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2666 DSAStackTy::DSAVarData TopDVar =
2668 unsigned NumLevels =
2673 return (NumLevels == CaptureLevel + 1 &&
2674 (TopDVar.CKind != OMPC_shared ||
2675 DSAStack->getDefaultDSA() == DSA_firstprivate));
2678 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2679 if (DVar.CKind != OMPC_shared)
2681 }
while (Level > 0);
2687void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2691 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2696 "Not in OpenMP declare variant scope!");
2698 OMPDeclareVariantScopes.pop_back();
2704 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2705 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2709 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2712 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2713 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2716 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2717 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2718 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2720 StringRef HostDevTy =
2722 Diag(
Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2723 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2724 diag::note_omp_marked_device_type_here)
2730 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2734 for (OMPDeclareVariantAttr *A :
2735 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2736 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2737 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2738 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2739 OMPDeclareTargetDeclAttr::getDeviceType(
2740 VariantFD->getMostRecentDecl());
2741 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2747 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2751 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2752 Diag(
Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2753 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2754 diag::note_omp_marked_device_type_here)
2772 DSAStack->setClauseParsingMode(OMPC_unknown);
2776static std::pair<ValueDecl *, bool>
2778 SourceRange &ERange,
bool AllowArraySection =
false,
2779 StringRef DiagType =
"");
2784 bool InscanFound =
false;
2791 if (
C->getClauseKind() != OMPC_reduction)
2793 auto *RC = cast<OMPReductionClause>(
C);
2794 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2796 InscanLoc = RC->getModifierLoc();
2799 if (RC->getModifier() == OMPC_REDUCTION_task) {
2809 S.
Diag(RC->getModifierLoc(),
2810 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2816 if (
C->getClauseKind() != OMPC_reduction)
2818 auto *RC = cast<OMPReductionClause>(
C);
2819 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2822 : RC->getModifierLoc(),
2823 diag::err_omp_inscan_reduction_expected);
2824 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2827 for (
Expr *Ref : RC->varlist()) {
2828 assert(Ref &&
"NULL expr in OpenMP nontemporal clause.");
2831 Expr *SimpleRefExpr = Ref;
2838 S.
Diag(Ref->getExprLoc(),
2839 diag::err_omp_reduction_not_inclusive_exclusive)
2840 << Ref->getSourceRange();
2854 const DSAStackTy::DSAVarData &DVar,
2855 bool IsLoopIterVar =
false);
2863 if (
const auto *
D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2865 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
2867 for (
Expr *DE : Clause->varlist()) {
2868 if (DE->isValueDependent() || DE->isTypeDependent()) {
2869 PrivateCopies.push_back(
nullptr);
2872 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2873 auto *VD = cast<VarDecl>(DRE->getDecl());
2875 const DSAStackTy::DSAVarData DVar =
2877 if (DVar.CKind == OMPC_lastprivate) {
2884 SemaRef, DE->getExprLoc(),
Type.getUnqualifiedType(),
2888 PrivateCopies.push_back(
nullptr);
2896 PrivateCopies.push_back(
nullptr);
2899 Clause->setPrivateCopies(PrivateCopies);
2903 if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
2905 for (
Expr *RefExpr : Clause->varlist()) {
2906 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
2909 Expr *SimpleRefExpr = RefExpr;
2913 PrivateRefs.push_back(RefExpr);
2918 const DSAStackTy::DSAVarData DVar =
2920 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2923 Clause->setPrivateRefs(PrivateRefs);
2926 if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
2927 for (
unsigned I = 0,
E = Clause->getNumberOfAllocators(); I <
E; ++I) {
2929 auto *DRE = dyn_cast<DeclRefExpr>(
D.Allocator->IgnoreParenImpCasts());
2933 if (!VD || !isa<VarDecl>(VD))
2935 DSAStackTy::DSAVarData DVar =
2941 Expr *MapExpr =
nullptr;
2943 DSAStack->checkMappableExprComponentListsForDecl(
2949 auto MI = MapExprComponents.rbegin();
2950 auto ME = MapExprComponents.rend();
2952 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2953 VD->getCanonicalDecl()) {
2954 MapExpr = MI->getAssociatedExpression();
2959 Diag(
D.Allocator->getExprLoc(),
2960 diag::err_omp_allocator_used_in_clauses)
2965 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2966 << MapExpr->getSourceRange();
2984 Expr *NumIterations,
Sema &SemaRef,
2985 Scope *S, DSAStackTy *Stack);
2989 DSAStackTy *Stack) {
2991 "loop exprs were not built");
2998 auto *LC = dyn_cast<OMPLinearClause>(
C);
3017 explicit VarDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3018 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3020 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3028 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3029 return std::make_unique<VarDeclFilterCCC>(*
this);
3038 explicit VarOrFuncDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3039 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3041 if (ND && ((isa<VarDecl>(ND) && ND->
getKind() == Decl::Var) ||
3042 isa<FunctionDecl>(ND))) {
3049 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3050 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3071 VarDeclFilterCCC CCC(
SemaRef);
3078 : diag::err_omp_expected_var_arg_suggest)
3080 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3082 Diag(
Id.getLoc(), Lookup.
empty() ? diag::err_undeclared_var_use
3083 : diag::err_omp_expected_var_arg)
3088 Diag(
Id.getLoc(), diag::err_omp_expected_var_arg) <<
Id.getName();
3097 Diag(
Id.getLoc(), diag::err_omp_global_var_arg)
3102 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3114 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3115 << getOpenMPDirectiveName(Kind) << VD;
3119 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3129 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3130 << getOpenMPDirectiveName(Kind) << VD;
3134 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3146 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3147 << getOpenMPDirectiveName(Kind) << VD;
3151 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3160 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3161 << getOpenMPDirectiveName(Kind) << VD;
3165 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3173 if (Kind == OMPD_threadprivate && VD->
isUsed() &&
3175 Diag(
Id.getLoc(), diag::err_omp_var_used)
3176 << getOpenMPDirectiveName(Kind) << VD;
3198class LocalVarRefChecker final
3204 if (
const auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3207 diag::err_omp_local_var_in_threadprivate_init)
3209 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3216 bool VisitStmt(
const Stmt *S) {
3217 for (
const Stmt *Child : S->children()) {
3218 if (Child && Visit(Child))
3223 explicit LocalVarRefChecker(
Sema &SemaRef) : SemaRef(SemaRef) {}
3232 for (
Expr *RefExpr : VarList) {
3233 auto *DE = cast<DeclRefExpr>(RefExpr);
3234 auto *VD = cast<VarDecl>(DE->getDecl());
3251 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3258 Diag(ILoc, diag::err_omp_ref_type_arg)
3259 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->
getType();
3263 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3271 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3276 Diag(ILoc, diag::err_omp_var_thread_local)
3281 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3289 LocalVarRefChecker Checker(
SemaRef);
3290 if (Checker.Visit(
Init))
3294 Vars.push_back(RefExpr);
3295 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3296 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3299 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3302 if (!Vars.empty()) {
3310static OMPAllocateDeclAttr::AllocatorTypeTy
3313 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3314 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3315 Allocator->isInstantiationDependent() ||
3316 Allocator->containsUnexpandedParameterPack())
3317 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3318 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3319 llvm::FoldingSetNodeID AEId;
3320 const Expr *AE = Allocator->IgnoreParenImpCasts();
3322 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3323 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3324 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3325 llvm::FoldingSetNodeID DAEId;
3328 if (AEId == DAEId) {
3329 AllocatorKindRes = AllocatorKind;
3333 return AllocatorKindRes;
3338 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3339 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3341 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3342 Expr *PrevAllocator = A->getAllocator();
3343 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3345 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3346 if (AllocatorsMatch &&
3347 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3348 Allocator && PrevAllocator) {
3349 const Expr *AE = Allocator->IgnoreParenImpCasts();
3351 llvm::FoldingSetNodeID AEId, PAEId;
3354 AllocatorsMatch = AEId == PAEId;
3356 if (!AllocatorsMatch) {
3358 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3362 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3364 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3368 Allocator ? Allocator->getExprLoc() : RefExpr->
getExprLoc();
3370 Allocator ? Allocator->getSourceRange() : RefExpr->
getSourceRange();
3372 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3374 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3375 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3376 << (Allocator ? 1 : 0) << AllocatorStream.str()
3377 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3379 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3380 << PrevAllocatorRange;
3388 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3390 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3399 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3400 Allocator->isInstantiationDependent() ||
3401 Allocator->containsUnexpandedParameterPack()))
3403 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3404 Allocator, Alignment, SR);
3407 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3413 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3414 Expr *Alignment =
nullptr;
3415 Expr *Allocator =
nullptr;
3416 if (Clauses.empty()) {
3426 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3427 Allocator = AC->getAllocator();
3428 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3429 Alignment = AC->getAlignment();
3431 llvm_unreachable(
"Unexpected clause on allocate directive");
3433 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3436 for (
Expr *RefExpr : VarList) {
3437 auto *DE = cast<DeclRefExpr>(RefExpr);
3438 auto *VD = cast<VarDecl>(DE->getDecl());
3442 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3450 AllocatorKind, Allocator))
3458 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3459 Diag(Allocator->getExprLoc(),
3460 diag::err_omp_expected_predefined_allocator)
3461 << Allocator->getSourceRange();
3465 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3471 Vars.push_back(RefExpr);
3490 Diag(
Loc, diag::err_omp_invalid_scope) <<
"requires";
3504 bool SkippedClauses) {
3505 if (!SkippedClauses && Assumptions.empty())
3506 Diag(
Loc, diag::err_omp_no_clause_for_directive)
3507 << llvm::omp::getAllAssumeClauseOptions()
3508 << llvm::omp::getOpenMPDirectiveName(DKind);
3512 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3513 OMPAssumeScoped.push_back(AA);
3518 if (Assumptions.empty())
3521 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3522 "Unexpected omp assumption directive!");
3523 OMPAssumeGlobal.push_back(AA);
3531 while (Ctx->getLexicalParent())
3533 DeclContexts.push_back(Ctx);
3534 while (!DeclContexts.empty()) {
3536 for (
auto *SubDC : DC->
decls()) {
3537 if (SubDC->isInvalidDecl())
3539 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3540 DeclContexts.push_back(CTD->getTemplatedDecl());
3541 llvm::append_range(DeclContexts, CTD->specializations());
3544 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3545 DeclContexts.push_back(DC);
3546 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3556 OMPAssumeScoped.pop_back();
3577 DSAStack->getEncounteredTargetLocs();
3579 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3580 for (
const OMPClause *CNew : ClauseList) {
3582 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3583 isa<OMPUnifiedAddressClause>(CNew) ||
3584 isa<OMPReverseOffloadClause>(CNew) ||
3585 isa<OMPDynamicAllocatorsClause>(CNew)) {
3586 Diag(
Loc, diag::err_omp_directive_before_requires)
3587 <<
"target" << getOpenMPClauseName(CNew->getClauseKind());
3589 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3593 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3594 Diag(
Loc, diag::err_omp_directive_before_requires)
3595 <<
"atomic" << getOpenMPClauseName(CNew->getClauseKind());
3596 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3602 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3610 const DSAStackTy::DSAVarData &DVar,
3611 bool IsLoopIterVar) {
3613 SemaRef.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3614 << getOpenMPClauseName(DVar.CKind);
3618 PDSA_StaticMemberShared,
3619 PDSA_StaticLocalVarShared,
3620 PDSA_LoopIterVarPrivate,
3621 PDSA_LoopIterVarLinear,
3622 PDSA_LoopIterVarLastprivate,
3623 PDSA_ConstVarShared,
3624 PDSA_GlobalVarShared,
3625 PDSA_TaskVarFirstprivate,
3626 PDSA_LocalVarPrivate,
3628 } Reason = PDSA_Implicit;
3629 bool ReportHint =
false;
3631 auto *VD = dyn_cast<VarDecl>(
D);
3632 if (IsLoopIterVar) {
3633 if (DVar.CKind == OMPC_private)
3634 Reason = PDSA_LoopIterVarPrivate;
3635 else if (DVar.CKind == OMPC_lastprivate)
3636 Reason = PDSA_LoopIterVarLastprivate;
3638 Reason = PDSA_LoopIterVarLinear;
3640 DVar.CKind == OMPC_firstprivate) {
3641 Reason = PDSA_TaskVarFirstprivate;
3642 ReportLoc = DVar.ImplicitDSALoc;
3644 Reason = PDSA_StaticLocalVarShared;
3646 Reason = PDSA_StaticMemberShared;
3648 Reason = PDSA_GlobalVarShared;
3650 Reason = PDSA_ConstVarShared;
3651 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3653 Reason = PDSA_LocalVarPrivate;
3655 if (Reason != PDSA_Implicit) {
3656 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3657 << Reason << ReportHint
3658 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3659 }
else if (DVar.ImplicitDSALoc.isValid()) {
3660 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3661 << getOpenMPClauseName(DVar.CKind);
3667 bool IsAggregateOrDeclareTarget) {
3670 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3671 Kind = OMPC_MAP_alloc;
3673 case OMPC_DEFAULTMAP_MODIFIER_to:
3676 case OMPC_DEFAULTMAP_MODIFIER_from:
3677 Kind = OMPC_MAP_from;
3679 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3680 Kind = OMPC_MAP_tofrom;
3682 case OMPC_DEFAULTMAP_MODIFIER_present:
3688 Kind = OMPC_MAP_alloc;
3690 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3692 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3693 case OMPC_DEFAULTMAP_MODIFIER_none:
3694 case OMPC_DEFAULTMAP_MODIFIER_default:
3699 if (IsAggregateOrDeclareTarget) {
3700 Kind = OMPC_MAP_tofrom;
3703 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3710class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3714 bool ErrorFound =
false;
3715 bool TryCaptureCXXThisMembers =
false;
3722 ImplicitMapModifier[DefaultmapKindNum];
3724 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3728 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3730 if (S->getDirectiveKind() == OMPD_atomic ||
3731 S->getDirectiveKind() == OMPD_critical ||
3732 S->getDirectiveKind() == OMPD_section ||
3733 S->getDirectiveKind() == OMPD_master ||
3734 S->getDirectiveKind() == OMPD_masked ||
3735 S->getDirectiveKind() == OMPD_scope ||
3736 S->getDirectiveKind() == OMPD_assume ||
3738 Visit(S->getAssociatedStmt());
3741 visitSubCaptures(S->getInnermostCapturedStmt());
3744 if (TryCaptureCXXThisMembers ||
3746 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3748 return C.capturesThis();
3750 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3751 TryCaptureCXXThisMembers =
true;
3752 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3753 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3760 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
3761 for (
Expr *Ref : FC->varlist())
3774 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3777 !Stack->getTopDSA(VD,
false).RefExpr &&
3778 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3779 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3780 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3781 Visit(CED->getInit());
3784 }
else if (VD->
isImplicit() || isa<OMPCapturedExprDecl>(VD))
3787 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3792 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3793 !Stack->isImplicitTaskFirstprivate(VD))
3796 if (Stack->isUsesAllocatorsDecl(VD))
3799 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
3801 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3805 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3806 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3809 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3810 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3811 !Stack->isImplicitTaskFirstprivate(VD))
3819 if (DVar.CKind == OMPC_unknown &&
3820 (Stack->getDefaultDSA() == DSA_none ||
3821 Stack->getDefaultDSA() == DSA_private ||
3822 Stack->getDefaultDSA() == DSA_firstprivate) &&
3823 isImplicitOrExplicitTaskingRegion(DKind) &&
3824 VarsWithInheritedDSA.count(VD) == 0) {
3825 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3826 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3827 Stack->getDefaultDSA() == DSA_private)) {
3828 DSAStackTy::DSAVarData DVar =
3829 Stack->getImplicitDSA(VD,
false);
3830 InheritedDSA = DVar.CKind == OMPC_unknown;
3833 VarsWithInheritedDSA[VD] =
E;
3834 if (Stack->getDefaultDSA() == DSA_none)
3849 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3850 OMPC_DEFAULTMAP_MODIFIER_none;
3851 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3852 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3856 if (!Stack->checkMappableExprComponentListsForDecl(
3861 auto MI = MapExprComponents.rbegin();
3862 auto ME = MapExprComponents.rend();
3863 return MI != ME && MI->getAssociatedDeclaration() == VD;
3865 VarsWithInheritedDSA[VD] =
E;
3871 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3872 OMPC_DEFAULTMAP_MODIFIER_present;
3873 if (IsModifierPresent) {
3874 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3875 OMPC_MAP_MODIFIER_present)) {
3876 ImplicitMapModifier[ClauseKind].push_back(
3877 OMPC_MAP_MODIFIER_present);
3883 !Stack->isLoopControlVariable(VD).first) {
3884 if (!Stack->checkMappableExprComponentListsForDecl(
3889 if (SemaRef.LangOpts.OpenMP >= 50)
3890 return !StackComponents.empty();
3893 return StackComponents.size() == 1 ||
3895 llvm::drop_begin(llvm::reverse(StackComponents)),
3896 [](const OMPClauseMappableExprCommon::
3897 MappableComponent &MC) {
3898 return MC.getAssociatedDeclaration() ==
3900 (isa<ArraySectionExpr>(
3901 MC.getAssociatedExpression()) ||
3902 isa<OMPArrayShapingExpr>(
3903 MC.getAssociatedExpression()) ||
3904 isa<ArraySubscriptExpr>(
3905 MC.getAssociatedExpression()));
3908 bool IsFirstprivate =
false;
3910 if (
const auto *RD =
3912 IsFirstprivate = RD->isLambda();
3914 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3915 if (IsFirstprivate) {
3916 ImplicitFirstprivate.emplace_back(
E);
3919 Stack->getDefaultmapModifier(ClauseKind);
3921 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3922 ImplicitMap[ClauseKind][
Kind].emplace_back(
E);
3932 DVar = Stack->hasInnermostDSA(
3935 return C == OMPC_reduction && !AppliedToPointee;
3944 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
3950 DVar = Stack->getImplicitDSA(VD,
false);
3952 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3953 DVar.CKind == OMPC_firstprivate) ||
3954 (Stack->getDefaultDSA() == DSA_private &&
3955 DVar.CKind == OMPC_private)) &&
3957 !Stack->isLoopControlVariable(VD).first) {
3958 if (Stack->getDefaultDSA() == DSA_private)
3959 ImplicitPrivate.push_back(
E);
3961 ImplicitFirstprivate.push_back(
E);
3968 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3969 Stack->addToParentTargetRegionLinkGlobals(
E);
3978 auto *FD = dyn_cast<FieldDecl>(
E->getMemberDecl());
3982 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
3985 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3989 !Stack->isLoopControlVariable(FD).first &&
3990 !Stack->checkMappableExprComponentListsForDecl(
3995 return isa<CXXThisExpr>(
3997 StackComponents.back().getAssociatedExpression())
4009 if (Stack->isClassPreviouslyMapped(TE->getType()))
4013 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4018 ImplicitMap[ClauseKind][
Kind].emplace_back(
E);
4027 DVar = Stack->hasInnermostDSA(
4030 return C == OMPC_reduction && !AppliedToPointee;
4039 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4045 DVar = Stack->getImplicitDSA(FD,
false);
4047 !Stack->isLoopControlVariable(FD).first) {
4052 if (DVar.CKind != OMPC_unknown)
4053 ImplicitFirstprivate.push_back(
E);
4062 const auto *VD = cast<ValueDecl>(
4063 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4064 if (!Stack->checkMappableExprComponentListsForDecl(
4070 auto CCI = CurComponents.rbegin();
4071 auto CCE = CurComponents.rend();
4072 for (const auto &SC : llvm::reverse(StackComponents)) {
4074 if (CCI->getAssociatedExpression()->getStmtClass() !=
4075 SC.getAssociatedExpression()->getStmtClass())
4076 if (!((isa<ArraySectionExpr>(
4077 SC.getAssociatedExpression()) ||
4078 isa<OMPArrayShapingExpr>(
4079 SC.getAssociatedExpression())) &&
4080 isa<ArraySubscriptExpr>(
4081 CCI->getAssociatedExpression())))
4084 const Decl *CCD = CCI->getAssociatedDeclaration();
4085 const Decl *SCD = SC.getAssociatedDeclaration();
4086 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4087 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4090 std::advance(CCI, 1);
4096 Visit(
E->getBase());
4098 }
else if (!TryCaptureCXXThisMembers) {
4099 Visit(
E->getBase());
4106 if (isa_and_nonnull<OMPPrivateClause>(
C))
4112 if (
C && !((isa<OMPFirstprivateClause>(
C) || isa<OMPMapClause>(
C)) &&
4114 for (
Stmt *CC :
C->children()) {
4121 VisitSubCaptures(S);
4130 for (
Stmt *
C : S->arguments()) {
4137 if (
Expr *Callee = S->getCallee()) {
4138 auto *CI =
Callee->IgnoreParenImpCasts();
4139 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4140 Visit(CE->getBase());
4141 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4145 void VisitStmt(
Stmt *S) {
4146 for (
Stmt *
C : S->children()) {
4157 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4159 VarDecl *VD = Cap.getCapturedVar();
4163 Stack->checkMappableExprComponentListsForDecl(
4170 Cap.getLocation(),
true);
4174 bool isErrorFound()
const {
return ErrorFound; }
4176 return ImplicitFirstprivate;
4181 return ImplicitMap[DK][MK];
4185 return ImplicitMapModifier[
Kind];
4188 return VarsWithInheritedDSA;
4192 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4193 DKind = S->getCurrentDirective();
4208 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4210 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4212 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4214 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4216 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4217 Stack->handleConstructTrait(Traits, ScopeEntry);
4228 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4229 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4231 if (LoopBoundSharing) {
4233 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4234 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4238 Params.push_back(std::make_pair(StringRef(),
QualType()));
4259 std::make_pair(
".global_tid.", KmpInt32Ty),
4260 std::make_pair(
".part_id.", KmpInt32PtrTy),
4261 std::make_pair(
".privates.", VoidPtrTy),
4266 std::make_pair(StringRef(),
QualType())
4277 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4280 Params.push_back(std::make_pair(StringRef(),
QualType()));
4287 std::make_pair(StringRef(),
QualType())
4309 std::make_pair(
".global_tid.", KmpInt32Ty),
4310 std::make_pair(
".part_id.", KmpInt32PtrTy),
4311 std::make_pair(
".privates.", VoidPtrTy),
4316 std::make_pair(
".lb.", KmpUInt64Ty),
4317 std::make_pair(
".ub.", KmpUInt64Ty),
4318 std::make_pair(
".st.", KmpInt64Ty),
4319 std::make_pair(
".liter.", KmpInt32Ty),
4320 std::make_pair(
".reductions.", VoidPtrTy),
4321 std::make_pair(StringRef(),
QualType())
4334 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4335 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4338 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4373 case OMPD_metadirective:
4376 llvm_unreachable(
"Unexpected capture region");
4392 case OMPD_interchange:
4405int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4412 return CaptureRegions.size();
4416 Expr *CaptureExpr,
bool WithInit,
4418 bool AsExpression) {
4419 assert(CaptureExpr);
4425 Ty =
C.getLValueReferenceType(Ty);
4427 Ty =
C.getPointerType(Ty);
4439 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4450 CD = cast<OMPCapturedExprDecl>(VD);
4489class CaptureRegionUnwinderRAII {
4496 CaptureRegionUnwinderRAII(
Sema &S,
bool &ErrorFound,
4498 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4499 ~CaptureRegionUnwinderRAII() {
4502 while (--ThisCaptureLevel >= 0)
4515 DSAStack->getCurrentDirective()))) {
4517 if (
const auto *RD =
Type.getCanonicalType()
4518 .getNonReferenceType()
4520 bool SavedForceCaptureByReferenceInTargetExecutable =
4521 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4522 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4524 if (RD->isLambda()) {
4525 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4527 RD->getCaptureFields(Captures, ThisCapture);
4530 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4535 }
else if (LC.getCaptureKind() ==
LCK_This) {
4538 ThisTy, ThisCapture->
getType()))
4543 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4544 SavedForceCaptureByReferenceInTargetExecutable);
4554 for (
const OMPClause *Clause : Clauses) {
4556 Ordered = cast<OMPOrderedClause>(Clause);
4558 Order = cast<OMPOrderClause>(Clause);
4559 if (Order->
getKind() != OMPC_ORDER_concurrent)
4562 if (Ordered && Order)
4566 if (Ordered && Order) {
4568 diag::err_omp_simple_clause_incompatible_with_ordered)
4569 << getOpenMPClauseName(OMPC_order)
4586 bool ErrorFound =
false;
4587 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4589 if (!S.isUsable()) {
4604 DSAStack->getCurrentDirective() == OMPD_target) &&
4608 auto *IRC = cast<OMPInReductionClause>(Clause);
4609 for (
Expr *
E : IRC->taskgroup_descriptors())
4621 if (
auto *
E = cast_or_null<Expr>(VarRef)) {
4625 DSAStack->setForceVarCapturing(
false);
4626 }
else if (CaptureRegions.size() > 1 ||
4627 CaptureRegions.back() != OMPD_unknown) {
4631 if (
Expr *
E =
C->getPostUpdateExpr())
4636 SC = cast<OMPScheduleClause>(Clause);
4638 OC = cast<OMPOrderedClause>(Clause);
4640 LCs.push_back(cast<OMPLinearClause>(Clause));
4651 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4656 diag::err_omp_simple_clause_incompatible_with_ordered)
4657 << getOpenMPClauseName(OMPC_schedule)
4659 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4670 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4679 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
4686 unsigned CompletedRegions = 0;
4691 if (ThisCaptureRegion != OMPD_unknown) {
4699 if (CaptureRegion == ThisCaptureRegion ||
4700 CaptureRegion == OMPD_unknown) {
4701 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4702 for (
Decl *
D : DS->decls())
4709 if (ThisCaptureRegion == OMPD_target) {
4713 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4714 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4717 if (
Expr *
E =
D.AllocatorTraits)
4724 if (ThisCaptureRegion == OMPD_parallel) {
4728 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4729 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4731 for (
Expr *
E : RC->copy_array_temps())
4735 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4736 for (
Expr *
E : AC->varlist())
4741 if (++CompletedRegions == CaptureRegions.size())
4752 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4755 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4756 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4759 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4760 << getOpenMPDirectiveName(CancelRegion);
4770 if (!Stack->getCurScope())
4775 bool NestingProhibited =
false;
4776 bool CloseNesting =
true;
4777 bool OrphanSeen =
false;
4780 ShouldBeInParallelRegion,
4781 ShouldBeInOrderedRegion,
4782 ShouldBeInTargetRegion,
4783 ShouldBeInTeamsRegion,
4784 ShouldBeInLoopSimdRegion,
4785 } Recommend = NoRecommend;
4789 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4792 if (SemaRef.
LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4793 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4794 CurrentRegion != OMPD_parallel &&
4796 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
4797 << getOpenMPDirectiveName(CurrentRegion);
4801 ((SemaRef.
LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4802 (SemaRef.
LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4803 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4804 CurrentRegion != OMPD_scan))) {
4817 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
4818 ? diag::err_omp_prohibited_region_simd
4819 : diag::warn_omp_nesting_simd)
4820 << (SemaRef.
LangOpts.OpenMP >= 50 ? 1 : 0);
4821 return CurrentRegion != OMPD_simd;
4823 if (EnclosingConstruct == OMPD_atomic) {
4826 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4829 if (CurrentRegion == OMPD_section) {
4834 if (EnclosingConstruct != OMPD_sections) {
4835 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4836 << (ParentRegion != OMPD_unknown)
4837 << getOpenMPDirectiveName(ParentRegion);
4845 if (ParentRegion == OMPD_unknown &&
4847 CurrentRegion != OMPD_cancellation_point &&
4848 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4852 if (SemaRef.
LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4853 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4855 EnclosingConstruct == OMPD_loop)) {
4856 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4857 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
4858 <<
true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4859 << getOpenMPDirectiveName(CurrentRegion);
4862 if (CurrentRegion == OMPD_cancellation_point ||
4863 CurrentRegion == OMPD_cancel) {
4876 if (CancelRegion == OMPD_taskgroup) {
4877 NestingProhibited = EnclosingConstruct != OMPD_task &&
4879 EnclosingConstruct != OMPD_taskloop);
4880 }
else if (CancelRegion == OMPD_sections) {
4881 NestingProhibited = EnclosingConstruct != OMPD_section &&
4882 EnclosingConstruct != OMPD_sections;
4884 NestingProhibited = CancelRegion != Leafs.back();
4886 OrphanSeen = ParentRegion == OMPD_unknown;
4887 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4894 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
4900 bool DeadLock = Stack->hasDirective(
4904 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
4905 PreviousCriticalLoc = Loc;
4912 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4914 if (PreviousCriticalLoc.
isValid())
4915 SemaRef.
Diag(PreviousCriticalLoc,
4916 diag::note_omp_previous_critical_region);
4919 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4929 llvm::is_contained({OMPD_masked, OMPD_master,
4930 OMPD_critical, OMPD_ordered},
4931 EnclosingConstruct);
4942 llvm::is_contained({OMPD_masked, OMPD_master,
4943 OMPD_critical, OMPD_ordered},
4944 EnclosingConstruct);
4945 Recommend = ShouldBeInParallelRegion;
4946 }
else if (CurrentRegion == OMPD_ordered) {
4955 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4958 Stack->isParentOrderedRegion());
4959 Recommend = ShouldBeInOrderedRegion;
4965 (SemaRef.
LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4966 (SemaRef.
LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4967 EnclosingConstruct != OMPD_target);
4968 OrphanSeen = ParentRegion == OMPD_unknown;
4969 Recommend = ShouldBeInTargetRegion;
4970 }
else if (CurrentRegion == OMPD_scan) {
4971 if (SemaRef.
LangOpts.OpenMP >= 50) {
4976 NestingProhibited = !llvm::is_contained(
4977 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4979 NestingProhibited =
true;
4981 OrphanSeen = ParentRegion == OMPD_unknown;
4982 Recommend = ShouldBeInLoopSimdRegion;
4986 EnclosingConstruct == OMPD_teams) {
4998 CurrentRegion != OMPD_loop &&
5000 CurrentRegion == OMPD_atomic);
5001 Recommend = ShouldBeInParallelRegion;
5003 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5009 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5010 Recommend = ShouldBeInTeamsRegion;
5016 NestingProhibited = EnclosingConstruct != OMPD_teams;
5017 Recommend = ShouldBeInTeamsRegion;
5019 if (!NestingProhibited &&
5026 NestingProhibited = Stack->hasDirective(
5030 OffendingRegion = K;
5036 CloseNesting =
false;
5038 if (NestingProhibited) {
5040 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5041 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5043 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5044 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5045 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5059 bool ErrorFound =
false;
5060 unsigned NamedModifiersNumber = 0;
5061 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5062 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5065 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5069 if (FoundNameModifiers[CurNM]) {
5070 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5071 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5072 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5074 }
else if (CurNM != OMPD_unknown) {
5075 NameModifierLoc.push_back(IC->getNameModifierLoc());
5076 ++NamedModifiersNumber;
5078 FoundNameModifiers[CurNM] = IC;
5079 if (CurNM == OMPD_unknown)
5085 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5086 S.
Diag(IC->getNameModifierLoc(),
5087 diag::err_omp_wrong_if_directive_name_modifier)
5088 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5095 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5096 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5097 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5098 diag::err_omp_no_more_if_clause);
5101 std::string Sep(
", ");
5102 unsigned AllowedCnt = 0;
5103 unsigned TotalAllowedNum =
5104 AllowedNameModifiers.size() - NamedModifiersNumber;
5105 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5108 if (!FoundNameModifiers[NM]) {
5110 Values += getOpenMPDirectiveName(NM);
5112 if (AllowedCnt + 2 == TotalAllowedNum)
5114 else if (AllowedCnt + 1 != TotalAllowedNum)
5119 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5120 diag::err_omp_unnamed_if_clause)
5121 << (TotalAllowedNum > 1) << Values;
5124 S.
Diag(
Loc, diag::note_omp_previous_named_if_clause);
5134 bool AllowArraySection,
5135 StringRef DiagType) {
5138 return std::make_pair(
nullptr,
true);
5150 } IsArrayExpr = NoArrayExpr;
5151 if (AllowArraySection) {
5152 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5153 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5154 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5155 Base = TempASE->getBase()->IgnoreParenImpCasts();
5157 IsArrayExpr = ArraySubscript;
5158 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5159 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5160 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5161 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5162 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5163 Base = TempASE->getBase()->IgnoreParenImpCasts();
5165 IsArrayExpr = OMPArraySection;
5171 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5172 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5173 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5175 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5176 !isa<FieldDecl>(ME->getMemberDecl()))) {
5177 if (IsArrayExpr != NoArrayExpr) {
5178 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5179 << IsArrayExpr << ERange;
5180 }
else if (!DiagType.empty()) {
5184 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5185 << DiagSelect << DiagType << ERange;
5189 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5190 : diag::err_omp_expected_var_name_member_expr)
5193 return std::make_pair(
nullptr,
false);
5195 return std::make_pair(
5202class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5203 DSAStackTy *S =
nullptr;
5207 return S->isUsesAllocatorsDecl(
E->getDecl())
5208 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5209 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5211 bool VisitStmt(
const Stmt *S) {
5212 for (
const Stmt *Child : S->children()) {
5213 if (Child && Visit(Child))
5218 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5225 "Expected non-dependent context.");
5226 auto AllocateRange =
5229 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5234 if (
Cl->getClauseKind() == OMPC_private) {
5235 auto *PC = cast<OMPPrivateClause>(
Cl);
5236 I = PC->private_copies().begin();
5237 It = PC->varlist_begin();
5238 Et = PC->varlist_end();
5239 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5240 auto *PC = cast<OMPFirstprivateClause>(
Cl);
5241 I = PC->private_copies().begin();
5242 It = PC->varlist_begin();
5243 Et = PC->varlist_end();
5244 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5245 auto *PC = cast<OMPLastprivateClause>(
Cl);
5246 I = PC->private_copies().begin();
5247 It = PC->varlist_begin();
5248 Et = PC->varlist_end();
5249 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5250 auto *PC = cast<OMPLinearClause>(
Cl);
5251 I = PC->privates().begin();
5252 It = PC->varlist_begin();
5253 Et = PC->varlist_end();
5254 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5255 auto *PC = cast<OMPReductionClause>(
Cl);
5256 I = PC->privates().begin();
5257 It = PC->varlist_begin();
5258 Et = PC->varlist_end();
5259 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5260 auto *PC = cast<OMPTaskReductionClause>(
Cl);
5261 I = PC->privates().begin();
5262 It = PC->varlist_begin();
5263 Et = PC->varlist_end();
5264 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5265 auto *PC = cast<OMPInReductionClause>(
Cl);
5266 I = PC->privates().begin();
5267 It = PC->varlist_begin();
5268 Et = PC->varlist_end();
5270 llvm_unreachable(
"Expected private clause.");
5272 for (
Expr *
E : llvm::make_range(It, Et)) {
5279 Expr *SimpleRefExpr =
E;
5282 DeclToCopy.try_emplace(Res.first,
5283 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5288 auto *AC = cast<OMPAllocateClause>(
C);
5292 AC->getAllocator()) {
5293 Expr *Allocator = AC->getAllocator();
5299 AllocatorChecker Checker(Stack);
5300 if (Checker.Visit(Allocator))
5301 S.
Diag(Allocator->getExprLoc(),
5302 diag::err_omp_allocator_not_in_uses_allocators)
5303 << Allocator->getSourceRange();
5305 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5311 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5314 S.
Diag(AC->getAllocator()->getExprLoc(),
5315 diag::warn_omp_allocate_thread_on_task_target_directive)
5316 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5318 for (
Expr *
E : AC->varlist()) {
5321 Expr *SimpleRefExpr =
E;
5324 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5327 diag::err_omp_expected_private_copy_for_allocate);
5330 VarDecl *PrivateVD = DeclToCopy[VD];
5332 AllocatorKind, AC->getAllocator()))
5335 Expr *Alignment =
nullptr;
5352 CaptureVars(
Sema &Actions) : BaseTransform(Actions) {}
5354 bool AlwaysRebuild() {
return true; }
5367 BodyStmts.push_back(NewDeclStmt);
5405 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5416 auto BuildVarRef = [&](
VarDecl *VD) {
5421 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5423 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5429 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5433 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5437 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5441 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5445 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5447 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5451 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5453 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5454 "Expected one of these relational operators");
5461 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5465 if (Rel == BO_GE || Rel == BO_GT)
5467 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5470 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5476 if (Rel == BO_LE || Rel == BO_GE) {
5488 Expr *Divisor = BuildVarRef(NewStep);
5489 if (Rel == BO_GE || Rel == BO_GT)
5492 Expr *DivisorMinusOne =
5497 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5507 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5508 BodyStmts.push_back(ResultAssign);
5513 return cast<CapturedStmt>(
5540 {
"Logical", LogicalTy},
5551 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5556 auto *CS = cast<CapturedDecl>(Actions.
CurContext);
5560 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5563 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5566 CaptureVars Recap(Actions);
5571 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5586 BO_Assign, TargetRef, Advanced));
5588 return cast<CapturedStmt>(
5599 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5601 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5603 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5604 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5606 assert(LCAssign->getOpcode() == BO_Assign &&
5607 "init part must be a loop variable assignment");
5608 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5609 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5611 llvm_unreachable(
"Cannot determine loop variable");
5614 Cond = For->getCond();
5615 Inc = For->getInc();
5616 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5617 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5619 LUVDecl = RangeFor->getLoopVariable();
5621 Cond = RangeFor->getCond();
5622 Inc = RangeFor->getInc();
5624 llvm_unreachable(
"unhandled kind of loop");
5633 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5634 LHS = CondBinExpr->getLHS();
5635 RHS = CondBinExpr->getRHS();
5636 CondRel = CondBinExpr->getOpcode();
5637 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5638 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5639 LHS = CondCXXOp->getArg(0);
5640 RHS = CondCXXOp->getArg(1);
5641 switch (CondCXXOp->getOperator()) {
5642 case OO_ExclaimEqual:
5654 case OO_GreaterEqual:
5658 llvm_unreachable(
"unexpected iterator operator");
5661 llvm_unreachable(
"unexpected loop condition");
5665 cast<DeclRefExpr>(LHS->
IgnoreImplicit())->getDecl() != LIVDecl) {
5666 std::swap(LHS, RHS);
5683 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5685 switch (IncUn->getOpcode()) {
5695 llvm_unreachable(
"unhandled unary increment operator");
5698 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction), LogicalTy, {});
5699 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5700 if (IncBin->getOpcode() == BO_AddAssign) {
5701 Step = IncBin->getRHS();
5702 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5706 llvm_unreachable(
"unhandled binary increment operator");
5707 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5708 switch (CondCXXOp->getOperator()) {
5711 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5715 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5718 Step = CondCXXOp->getArg(1);
5725 llvm_unreachable(
"unhandled overloaded increment operator");
5728 llvm_unreachable(
"unknown increment expression");
5733 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5736 nullptr,
nullptr, {},
nullptr);
5738 LoopVarFunc, LVRef);
5743 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5750 "Loop transformation directive expected");
5751 return LoopTransform;
5758 Expr *UnresolvedMapper);
5770 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5771 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5775 auto *MI =
C->mapperlist_begin();
5776 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
5796 ElemType = ATy->getElementType();
5799 CanonType = ElemType;
5804 1, {CanonType,
nullptr});
5805 llvm::DenseMap<const Type *, Expr *>
Visited;
5808 while (!Types.empty()) {
5811 std::tie(BaseType, CurFD) = Types.pop_back_val();
5812 while (ParentChain.back().second == 0)
5813 ParentChain.pop_back();
5814 --ParentChain.back().second;
5830 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5841 Expr *BaseExpr = OE;
5842 for (
const auto &
P : ParentChain) {
5860 SubExprs.push_back(BaseExpr);
5864 bool FirstIter =
true;
5874 ParentChain.emplace_back(CurFD, 1);
5876 ++ParentChain.back().second;
5878 Types.emplace_back(FieldTy, FD);
5882 if (SubExprs.empty())
5887 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
5888 MapperIdScopeSpec, MapperId,
C->getMapType(),
5891 Clauses.push_back(NewClause);
5906 if (
D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5908 if (
C->getBindKind() == OMPC_BIND_parallel) {
5909 TeamsLoopCanBeParallelFor =
false;
5914 for (
const Stmt *Child :
D->children())
5924 bool IsOpenMPAPI =
false;
5925 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
5927 std::string Name = FD->getNameInfo().getAsString();
5928 IsOpenMPAPI = Name.find(
"omp_") == 0;
5930 TeamsLoopCanBeParallelFor =
5931 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5932 if (!TeamsLoopCanBeParallelFor)
5935 for (
const Stmt *Child :
C->children())
5943 Visit(S->getCapturedDecl()->getBody());
5946 void VisitStmt(
const Stmt *S) {
5949 for (
const Stmt *Child : S->children())
5953 explicit TeamsLoopChecker(
Sema &SemaRef)
5954 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
5957 bool TeamsLoopCanBeParallelFor;
5962 TeamsLoopChecker Checker(SemaRef);
5963 Checker.Visit(AStmt);
5964 return Checker.teamsLoopCanBeParallelFor();
5978 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5979 BindKind = BC->getBindKind();
5991 BindKind = OMPC_BIND_thread;
5993 getLeafConstructsOrSelf(ParentDirective);
5995 if (ParentDirective == OMPD_unknown) {
5997 diag::err_omp_bind_required_on_loop);
5998 }
else if (ParentLeafs.back() == OMPD_parallel) {
5999 BindKind = OMPC_BIND_parallel;
6000 }
else if (ParentLeafs.back() == OMPD_teams) {
6001 BindKind = OMPC_BIND_teams;
6009 ClausesWithImplicit.push_back(
C);
6013 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6015 if (
C->getClauseKind() == OMPC_reduction)
6017 diag::err_omp_loop_reduction_clause);
6024 BindKind, StartLoc)) {
6031 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6034 bool ErrorFound =
false;
6035 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6039 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
6042 DSAAttrChecker DSAChecker(
DSAStack,
SemaRef, cast<CapturedStmt>(AStmt));
6045 while (--ThisCaptureLevel >= 0)
6046 S = cast<CapturedStmt>(S)->getCapturedStmt();
6047 DSAChecker.Visit(S);
6051 auto *CS = cast<CapturedStmt>(AStmt);
6055 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6057 DSAChecker.visitSubCaptures(CS);
6059 if (DSAChecker.isErrorFound())
6062 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6065 DSAChecker.getImplicitFirstprivate());
6070 ImplicitMapModifiers[DefaultmapKindNum];
6072 ImplicitMapModifiersLoc[DefaultmapKindNum];
6076 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6077 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6078 PresentModifierLocs[DMC->getDefaultmapKind()] =
6079 DMC->getDefaultmapModifierLoc();
6081 for (
unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6083 for (
unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6086 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6089 DSAChecker.getImplicitMapModifier(K);
6090 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6091 ImplicitModifier.end());
6092 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6093 ImplicitModifier.size(), PresentModifierLocs[VC]);
6097 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6098 for (
Expr *
E : IRC->taskgroup_descriptors())
6100 ImplicitFirstprivates.emplace_back(
E);
6105 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6106 ImplicitFirstprivates.push_back(DC->getEventHandler());
6108 if (!ImplicitFirstprivates.empty()) {
6112 ClausesWithImplicit.push_back(
Implicit);
6113 ErrorFound = cast<OMPFirstprivateClause>(
Implicit)->varlist_size() !=
6114 ImplicitFirstprivates.size();
6119 if (!ImplicitPrivates.empty()) {
6123 ClausesWithImplicit.push_back(
Implicit);
6124 ErrorFound = cast<OMPPrivateClause>(
Implicit)->varlist_size() !=
6125 ImplicitPrivates.size();
6134 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6138 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6139 for (
Expr *
E : RC->varlist())
6141 ImplicitExprs.emplace_back(
E);
6143 if (!ImplicitExprs.empty()) {
6149 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6152 ClausesWithImplicit.emplace_back(
Implicit);
6155 for (
unsigned I = 0,
E = DefaultmapKindNum; I <
E; ++I) {
6156 int ClauseKindCnt = -1;
6159 if (ImplicitMap.empty())
6165 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6166 MapperIdScopeSpec, MapperId, K,
true,
6169 ClausesWithImplicit.emplace_back(
Implicit);
6170 ErrorFound |= cast<OMPMapClause>(
Implicit)->varlist_size() !=
6181 ClausesWithImplicit);
6191 VarsWithInheritedDSA);
6202 assert(ClausesWithImplicit.empty() &&
6203 "reverse directive does not support any clauses");
6206 case OMPD_interchange:
6212 VarsWithInheritedDSA);
6216 EndLoc, VarsWithInheritedDSA);
6223 assert(ClausesWithImplicit.empty() &&
6224 "No clauses are allowed for 'omp section' directive");
6232 assert(ClausesWithImplicit.empty() &&
6233 "No clauses are allowed for 'omp master' directive");
6244 case OMPD_parallel_for:
6246 EndLoc, VarsWithInheritedDSA);
6248 case OMPD_parallel_for_simd:
6250 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6256 case OMPD_parallel_master:
6260 case OMPD_parallel_masked:
6264 case OMPD_parallel_sections:
6272 case OMPD_taskyield:
6273 assert(ClausesWithImplicit.empty() &&
6274 "No clauses are allowed for 'omp taskyield' directive");
6275 assert(AStmt ==
nullptr &&
6276 "No associated statement allowed for 'omp taskyield' directive");
6280 assert(AStmt ==
nullptr &&
6281 "No associated statement allowed for 'omp error' directive");
6285 assert(ClausesWithImplicit.empty() &&
6286 "No clauses are allowed for 'omp barrier' directive");
6287 assert(AStmt ==
nullptr &&
6288 "No associated statement allowed for 'omp barrier' directive");
6292 assert(AStmt ==
nullptr &&
6293 "No associated statement allowed for 'omp taskwait' directive");
6296 case OMPD_taskgroup:
6301 assert(AStmt ==
nullptr &&
6302 "No associated statement allowed for 'omp flush' directive");
6306 assert(AStmt ==
nullptr &&
6307 "No associated statement allowed for 'omp depobj' directive");
6311 assert(AStmt ==
nullptr &&
6312 "No associated statement allowed for 'omp scan' directive");
6331 case OMPD_target_parallel:
6335 case OMPD_target_parallel_for:
6337 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6339 case OMPD_cancellation_point:
6340 assert(ClausesWithImplicit.empty() &&
6341 "No clauses are allowed for 'omp cancellation point' directive");
6342 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6343 "cancellation point' directive");
6347 assert(AStmt ==
nullptr &&
6348 "No associated statement allowed for 'omp cancel' directive");
6352 case OMPD_target_data:
6356 case OMPD_target_enter_data:
6360 case OMPD_target_exit_data:
6366 EndLoc, VarsWithInheritedDSA);
6368 case OMPD_taskloop_simd:
6370 EndLoc, VarsWithInheritedDSA);
6372 case OMPD_master_taskloop:
6374 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6376 case OMPD_masked_taskloop:
6378 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6380 case OMPD_master_taskloop_simd:
6382 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6384 case OMPD_masked_taskloop_simd:
6386 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6388 case OMPD_parallel_master_taskloop:
6390 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6392 case OMPD_parallel_masked_taskloop:
6394 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6396 case OMPD_parallel_master_taskloop_simd:
6398 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6400 case OMPD_parallel_masked_taskloop_simd:
6402 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6404 case OMPD_distribute:
6406 EndLoc, VarsWithInheritedDSA);
6408 case OMPD_target_update:
6412 case OMPD_distribute_parallel_for:
6414 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6416 case OMPD_distribute_parallel_for_simd:
6418 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6420 case OMPD_distribute_simd:
6422 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6424 case OMPD_target_parallel_for_simd:
6426 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6428 case OMPD_target_simd:
6430 EndLoc, VarsWithInheritedDSA);
6432 case OMPD_teams_distribute:
6434 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6436 case OMPD_teams_distribute_simd:
6438 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6440 case OMPD_teams_distribute_parallel_for_simd:
6442 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6444 case OMPD_teams_distribute_parallel_for:
6446 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6448 case OMPD_target_teams:
6452 case OMPD_target_teams_distribute:
6454 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6456 case OMPD_target_teams_distribute_parallel_for:
6458 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6460 case OMPD_target_teams_distribute_parallel_for_simd:
6462 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6464 case OMPD_target_teams_distribute_simd:
6466 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6469 assert(AStmt ==
nullptr &&
6470 "No associated statement allowed for 'omp interop' directive");
6479 EndLoc, VarsWithInheritedDSA);
6481 case OMPD_teams_loop:
6483 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6485 case OMPD_target_teams_loop:
6487 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6489 case OMPD_parallel_loop:
6491 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6493 case OMPD_target_parallel_loop:
6495 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6497 case OMPD_declare_target:
6498 case OMPD_end_declare_target:
6499 case OMPD_threadprivate:
6501 case OMPD_declare_reduction:
6502 case OMPD_declare_mapper:
6503 case OMPD_declare_simd:
6505 case OMPD_declare_variant:
6506 case OMPD_begin_declare_variant:
6507 case OMPD_end_declare_variant:
6508 llvm_unreachable(
"OpenMP Directive is not allowed");
6511 llvm_unreachable(
"Unknown OpenMP directive");
6514 ErrorFound = Res.
isInvalid() || ErrorFound;
6518 if (
DSAStack->getDefaultDSA() == DSA_none ||
6519 DSAStack->getDefaultDSA() == DSA_private ||
6520 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6523 switch (
C->getClauseKind()) {
6524 case OMPC_num_threads:
6525 case OMPC_dist_schedule:
6532 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_target)
6536 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_parallel)
6542 case OMPC_grainsize:
6543 case OMPC_num_tasks:
6546 case OMPC_novariants:
6547 case OMPC_nocontext:
6554 case OMPC_num_teams:
6555 case OMPC_thread_limit:
6562 case OMPC_proc_bind:
6564 case OMPC_firstprivate:
6565 case OMPC_lastprivate:
6567 case OMPC_reduction:
6568 case OMPC_task_reduction:
6569 case OMPC_in_reduction:
6573 case OMPC_copyprivate:
6576 case OMPC_mergeable:
6593 case OMPC_defaultmap:
6596 case OMPC_use_device_ptr:
6597 case OMPC_use_device_addr:
6598 case OMPC_is_device_ptr:
6599 case OMPC_has_device_addr:
6600 case OMPC_nontemporal:
6603 case OMPC_inclusive:
6604 case OMPC_exclusive:
6605 case OMPC_uses_allocators:
6610 case OMPC_allocator:
6613 case OMPC_threadprivate:
6616 case OMPC_unified_address:
6617 case OMPC_unified_shared_memory:
6618 case OMPC_reverse_offload:
6619 case OMPC_dynamic_allocators:
6620 case OMPC_atomic_default_mem_order:
6621 case OMPC_device_type:
6628 llvm_unreachable(
"Unexpected clause");
6630 for (
Stmt *CC :
C->children()) {
6632 DSAChecker.Visit(CC);
6635 for (
const auto &
P : DSAChecker.getVarsWithInheritedDSA())
6636 VarsWithInheritedDSA[
P.getFirst()] =
P.getSecond();
6638 for (
const auto &
P : VarsWithInheritedDSA) {
6639 if (
P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(
P.getFirst()))
6642 if (
DSAStack->getDefaultDSA() == DSA_none ||
6643 DSAStack->getDefaultDSA() == DSA_private ||
6644 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6645 Diag(
P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6646 <<
P.first <<
P.second->getSourceRange();
6647 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6649 Diag(
P.second->getExprLoc(),
6650 diag::err_omp_defaultmap_no_attr_for_variable)
6651 <<
P.first <<
P.second->getSourceRange();
6653 diag::note_omp_defaultmap_attr_none);
6659 if (isAllowedClauseForDirective(
D, OMPC_if,
getLangOpts().OpenMP))
6660 AllowedNameModifiers.push_back(
D);
6662 if (!AllowedNameModifiers.empty())
6676 DSAStack->addTargetDirLocation(StartLoc);
6687 assert(Aligneds.size() == Alignments.size());
6688 assert(Linears.size() == LinModifiers.size());
6689 assert(Linears.size() == Steps.size());
6690 if (!DG || DG.
get().isNull())
6693 const int SimdId = 0;
6694 if (!DG.
get().isSingleDecl()) {
6695 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6699 Decl *ADecl = DG.
get().getSingleDecl();
6700 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6701 ADecl = FTD->getTemplatedDecl();
6703 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6705 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6721 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6722 const Expr *UniformedLinearThis =
nullptr;
6723 for (
const Expr *
E : Uniforms) {
6725 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6726 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6727 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6728 FD->getParamDecl(PVD->getFunctionScopeIndex())
6730 UniformedArgs.try_emplace(PVD->getCanonicalDecl(),
E);
6733 if (isa<CXXThisExpr>(
E)) {
6734 UniformedLinearThis =
E;
6738 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6748 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6749 const Expr *AlignedThis =
nullptr;
6750 for (
const Expr *
E : Aligneds) {
6752 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6753 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6755 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6756 FD->getParamDecl(PVD->getFunctionScopeIndex())
6760 if (AlignedArgs.count(CanonPVD) > 0) {
6762 << 1 << getOpenMPClauseName(OMPC_aligned)
6764 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6765 diag::note_omp_explicit_dsa)
6766 << getOpenMPClauseName(OMPC_aligned);
6769 AlignedArgs[CanonPVD] =
E;
6771 .getNonReferenceType()
6772 .getUnqualifiedType()
6773 .getCanonicalType();
6778 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6783 if (isa<CXXThisExpr>(
E)) {
6788 << getOpenMPClauseName(OMPC_aligned);
6794 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6801 for (
Expr *
E : Alignments) {
6805 NewAligns.push_back(Align.
get());
6816 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6817 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
6818 auto MI = LinModifiers.begin();
6819 for (
const Expr *
E : Linears) {
6823 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6824 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6826 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6827 FD->getParamDecl(PVD->getFunctionScopeIndex())
6831 if (LinearArgs.count(CanonPVD) > 0) {
6833 << getOpenMPClauseName(OMPC_linear)
6835 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6836 diag::note_omp_explicit_dsa)
6837 << getOpenMPClauseName(OMPC_linear);
6841 if (UniformedArgs.count(CanonPVD) > 0) {
6843 << getOpenMPClauseName(OMPC_linear)
6845 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6846 diag::note_omp_explicit_dsa)
6847 << getOpenMPClauseName(OMPC_uniform);
6850 LinearArgs[CanonPVD] =
E;
6856 PVD->getOriginalType(),
6861 if (isa<CXXThisExpr>(
E)) {
6862 if (UniformedLinearThis) {
6864 << getOpenMPClauseName(OMPC_linear)
6865 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6867 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
6868 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6872 UniformedLinearThis =
E;
6881 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6883 Expr *Step =
nullptr;
6884 Expr *NewStep =
nullptr;
6886 for (
Expr *
E : Steps) {
6888 if (Step ==
E || !
E) {
6889 NewSteps.push_back(
E ? NewStep :
nullptr);
6893 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6894 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6896 if (UniformedArgs.count(CanonPVD) == 0) {
6903 NewSteps.push_back(Step);
6922 NewSteps.push_back(NewStep);
6924 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6926 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
6927 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
6928 const_cast<Expr **
>(Linears.data()), Linears.size(),
6929 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
6930 NewSteps.data(), NewSteps.size(), SR);
6940 "Unexpected directive category");
6949 llvm_unreachable(
"Unknown OpenMP directive");
6958 "Expected function type with prototype.");
6960 "Expected function with type with no prototype.");
6962 "Expected function with prototype.");
6970 Param->setScopeInfo(0, Params.size());
6971 Param->setImplicit();
6972 Params.push_back(Param);
6975 FD->setParams(Params);
6982 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
6983 FD = UTemplDecl->getTemplatedDecl();
6985 FD = cast<FunctionDecl>(
D);
6986 assert(FD &&
"Expected a function declaration!");
6992 for (OMPAssumeAttr *AA : OMPAssumeScoped)
6995 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
6999SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7000 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7005 if (!
D.getIdentifier())
7008 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7011 bool IsTemplated = !TemplateParamLists.empty();
7013 !DVScope.TI->isExtensionActive(
7014 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7031 for (
auto *Candidate : Lookup) {
7032 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7034 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7035 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7036 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7037 UDecl = FTD->getTemplatedDecl();
7038 }
else if (!IsTemplated)
7039 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7053 FType, UDeclTy,
false,
7060 Bases.push_back(UDecl);
7063 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7064 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7066 if (Bases.empty() && UseImplicitBase) {
7070 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7071 Bases.push_back(BaseTemplD->getTemplatedDecl());
7073 Bases.push_back(cast<FunctionDecl>(BaseD));
7076 std::string MangledName;
7077 MangledName +=
D.getIdentifier()->getName();
7079 MangledName += DVScope.NameSuffix;
7094 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
7095 FD = UTemplDecl->getTemplatedDecl();
7097 FD = cast<FunctionDecl>(
D);
7103 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7104 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7110 BaseFD->addAttr(OMPDeclareVariantA);
7129 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7132 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7135 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7139 std::function<void(StringRef)> DiagUnknownTrait = [
this,
7140 CE](StringRef ISATrait) {
7154 while (CalleeFnDecl) {
7155 for (OMPDeclareVariantAttr *A :
7157 Expr *VariantRef = A->getVariantFuncRef();
7159 VariantMatchInfo VMI;
7162 if (!isVariantApplicableInContext(VMI, OMPCtx,
7166 VMIs.push_back(VMI);
7167 Exprs.push_back(VariantRef);
7175 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7178 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7179 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7195 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7196 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7198 Context, MemberCall->getImplicitObjectArgument(),
7200 MemberCall->getValueKind(), MemberCall->getObjectKind());
7203 RParenLoc, ExecConfig);
7205 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7206 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7208 CalleeFnType, NewCalleeFnDecl->
getType(),
7219 VMIs.erase(VMIs.begin() + BestIdx);
7220 Exprs.erase(Exprs.begin() + BestIdx);
7221 }
while (!VMIs.empty());
7228std::optional<std::pair<FunctionDecl *, Expr *>>
7232 unsigned NumAppendArgs,
7235 if (!DG || DG.
get().isNull())
7236 return std::nullopt;
7238 const int VariantId = 1;
7240 if (!DG.
get().isSingleDecl()) {
7241 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7243 return std::nullopt;
7245 Decl *ADecl = DG.
get().getSingleDecl();
7246 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7247 ADecl = FTD->getTemplatedDecl();
7250 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7254 return std::nullopt;
7257 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7260 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7263 if (HasMultiVersionAttributes(FD)) {
7264 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7266 return std::nullopt;
7271 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7276 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7278 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7283 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7284 return std::nullopt;
7287 auto ShouldDelayChecks = [](
Expr *&
E,
bool) {
7293 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7295 return std::make_pair(FD, VariantRef);
7298 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&
E,
7299 bool IsScore) ->
bool {
7305 Diag(
E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7313 diag::err_omp_declare_variant_user_condition_not_constant)
7319 return std::nullopt;
7322 if (NumAppendArgs) {
7325 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7327 return std::nullopt;
7336 TD = dyn_cast_or_null<TypeDecl>(ND);
7339 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7340 return std::nullopt;
7343 if (PTy->isVariadic()) {
7344 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7345 return std::nullopt;
7348 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7349 Params.insert(Params.end(), NumAppendArgs, InteropType);
7350 AdjustedFnType = Context.
getFunctionType(PTy->getReturnType(), Params,
7351 PTy->getExtProtoInfo());
7359 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7360 if (Method && !Method->isStatic()) {
7361 const Type *ClassType =
7375 return std::nullopt;
7377 VariantRef = ER.
get();
7385 false, Sema::AllowedExplicit::None,
7391 diag::err_omp_declare_variant_incompat_types)
7393 << ((Method && !Method->isStatic()) ? FnPtrType : FD->
getType())
7395 return std::nullopt;
7400 return std::nullopt;
7403 if (Method && !Method->isStatic()) {
7404 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7405 if (
auto *UO = dyn_cast<UnaryOperator>(
7407 VariantRefCast = UO->getSubExpr();
7416 return std::nullopt;
7424 return std::nullopt;
7426 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7430 return std::nullopt;
7435 diag::err_omp_declare_variant_same_base_function)
7437 return std::nullopt;
7446 diag::err_omp_declare_variant_incompat_types)
7447 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7449 return std::nullopt;
7454 else if (NewFD->getType()->isFunctionNoProtoType())
7460 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7462 diag::warn_omp_declare_variant_marked_as_declare_variant)
7465 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7466 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7467 return std::nullopt;
7470 enum DoesntSupport {
7479 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7480 if (CXXFD->isVirtual()) {
7483 return std::nullopt;
7486 if (isa<CXXConstructorDecl>(FD)) {
7489 return std::nullopt;
7492 if (isa<CXXDestructorDecl>(FD)) {
7495 return std::nullopt;
7499 if (FD->isDeleted()) {
7502 return std::nullopt;
7505 if (FD->isDefaulted()) {
7508 return std::nullopt;
7511 if (FD->isConstexpr()) {
7513 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7514 return std::nullopt;
7524 SemaRef.
PDiag(diag::err_omp_declare_variant_doesnt_support)),
7530 return std::nullopt;
7531 return std::make_pair(FD, cast<Expr>(DRE));
7547 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7548 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7550 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7551 VariantMatchInfo VMI;
7553 if (!llvm::is_contained(
7554 VMI.ConstructTraits,
7555 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7556 if (!AllAdjustArgs.empty())
7557 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7558 << getOpenMPClauseName(OMPC_adjust_args);
7559 if (!AppendArgs.empty())
7560 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7561 << getOpenMPClauseName(OMPC_append_args);
7571 for (
Expr *
E : AllAdjustArgs) {
7573 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E)) {
7574 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7576 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7580 if (!AdjustVars.insert(CanonPVD).second) {
7581 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7590 Diag(
E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7594 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7596 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7597 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7598 AdjustArgsNeedDevicePtr.size(),
7599 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7605 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7606 assert(CS &&
"Captured statement expected");
7615 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7644struct LoopIterationSpace final {
7647 bool IsStrictCompare =
false;
7649 Expr *PreCond =
nullptr;
7652 Expr *NumIterations =
nullptr;
7654 Expr *CounterVar =
nullptr;
7656 Expr *PrivateCounterVar =
nullptr;
7658 Expr *CounterInit =
nullptr;
7661 Expr *CounterStep =
nullptr;
7663 bool Subtract =
false;
7673 Expr *MinValue =
nullptr;
7677 Expr *MaxValue =
nullptr;
7679 bool IsNonRectangularLB =
false;
7681 bool IsNonRectangularUB =
false;
7684 unsigned LoopDependentIdx = 0;
7688 Expr *FinalCondition =
nullptr;
7695 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7696 VarDecl *ForbiddenVar =
nullptr;
7700 explicit ForSubExprChecker(
7701 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7702 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {}
7706 bool shouldVisitImplicitCode()
const {
return true; }
7710 if (!isa<VarDecl, BindingDecl>(VD))
7713 if (
V->getType()->isReferenceType()) {
7723 Decl *Canon =
V->getCanonicalDecl();
7724 if (CollapsedLoopVarDecls.contains(Canon)) {
7733 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
7734 SourceRange getErrRange()
const {
return ErrLoc; }
7740class OpenMPIterationSpaceChecker {
7744 bool SupportsNonRectangular;
7752 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7762 Expr *LCRef =
nullptr;
7768 Expr *Step =
nullptr;
7775 std::optional<bool> TestIsLessOp;
7777 bool TestIsStrictOp =
false;
7779 bool SubtractStep =
false;
7784 std::optional<unsigned> InitDependOnLC;
7787 std::optional<unsigned> CondDependOnLC;
7789 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
7790 bool IsInitializer);
7796 OpenMPIterationSpaceChecker(
7797 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
7799 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7800 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7801 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7802 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7805 bool checkAndSetInit(
Stmt *S,
bool EmitDiags =
true);
7808 bool checkAndSetCond(
Expr *S);
7811 bool checkAndSetInc(
Expr *S);
7813 ValueDecl *getLoopDecl()
const {
return LCDecl; }
7815 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
7817 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
7819 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
7821 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
7823 bool shouldSubtractStep()
const {
return SubtractStep; }
7825 bool isStrictTestOp()
const {
return TestIsStrictOp; }
7827 Expr *buildNumIterations(
7829 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7833 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7836 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7837 DSAStackTy &DSA)
const;
7840 Expr *buildPrivateCounterVar()
const;
7844 Expr *buildCounterStep()
const;
7848 buildOrderedLoopData(
Scope *S,
Expr *Counter,
7849 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7853 std::pair<Expr *, Expr *> buildMinMaxValues(
7854 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7856 Expr *buildFinalCondition(
Scope *S)
const;
7858 bool dependent()
const;
7860 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
7862 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
7864 unsigned getLoopDependentIdx()
const {
7865 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7871 bool checkAndSetIncRHS(
Expr *RHS);
7876 bool setUB(
Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
7879 bool setStep(
Expr *NewStep,
bool Subtract);
7882bool OpenMPIterationSpaceChecker::dependent()
const {
7884 assert(!LB && !UB && !Step);
7892bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
7894 Expr *NewLB,
bool EmitDiags) {
7896 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
7897 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7901 LCRef = NewLCRefExpr;
7902 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7904 if ((Ctor->isCopyOrMoveConstructor() ||
7905 Ctor->isConvertingConstructor(
false)) &&
7906 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
7910 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
7914bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
7918 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
7919 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7924 TestIsLessOp = LessOp;
7925 TestIsStrictOp = StrictOp;
7926 ConditionSrcRange = SR;
7928 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
7932bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
7934 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
7944 NewStep = Val.
get();
7957 std::optional<llvm::APSInt>
Result =
7968 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7969 if (UB && (IsConstZero ||
7970 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7971 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7973 diag::err_omp_loop_incr_not_compatible)
7975 SemaRef.
Diag(ConditionLoc,
7976 diag::note_omp_loop_cond_requires_compatible_incr)
7977 << *TestIsLessOp << ConditionSrcRange;
7980 if (*TestIsLessOp == Subtract) {
7984 Subtract = !Subtract;
7989 SubtractStep = Subtract;
7996class LoopCounterRefChecker final
8003 bool IsInitializer =
true;
8004 bool SupportsNonRectangular;
8005 unsigned BaseLoopId = 0;
8008 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8009 << (IsInitializer ? 0 : 1);
8012 const auto &&
Data = Stack.isLoopControlVariable(VD);
8018 llvm::raw_svector_ostream OS(Name);
8022 diag::err_omp_wrong_dependency_iterator_type)
8024 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8027 if (
Data.first && !SupportsNonRectangular) {
8028 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_invariant_dependency);
8032 (DepDecl || (PrevDepDecl &&
8034 if (!DepDecl && PrevDepDecl)
8035 DepDecl = PrevDepDecl;
8037 llvm::raw_svector_ostream OS(Name);
8041 diag::err_omp_invariant_or_linear_dependency)
8047 BaseLoopId =
Data.first;
8055 if (isa<VarDecl>(VD))
8056 return checkDecl(
E, VD);
8062 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8063 return checkDecl(
E, VD);
8067 bool VisitStmt(
const Stmt *S) {
8069 for (
const Stmt *Child : S->children())
8070 Res = (Child && Visit(Child)) || Res;
8073 explicit LoopCounterRefChecker(
Sema &SemaRef, DSAStackTy &Stack,
8074 const ValueDecl *CurLCDecl,
bool IsInitializer,
8076 bool SupportsNonRectangular =
true)
8077 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8078 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8079 SupportsNonRectangular(SupportsNonRectangular) {}
8080 unsigned getBaseLoopId()
const {
8081 assert(CurLCDecl &&
"Expected loop dependency.");
8085 assert(CurLCDecl &&
"Expected loop dependency.");
8091std::optional<unsigned>
8092OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8093 bool IsInitializer) {
8095 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8096 DepDecl, SupportsNonRectangular);
8097 if (LoopStmtChecker.Visit(S)) {
8098 DepDecl = LoopStmtChecker.getDepDecl();
8099 return LoopStmtChecker.getBaseLoopId();
8101 return std::nullopt;
8104bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8115 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8119 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8120 if (!ExprTemp->cleanupsHaveSideEffects())
8121 S = ExprTemp->getSubExpr();
8123 if (!CollapsedLoopVarDecls.empty()) {
8124 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8125 if (!FSEC.TraverseStmt(S)) {
8127 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8133 InitSrcRange = S->getSourceRange();
8134 if (
Expr *
E = dyn_cast<Expr>(S))
8136 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8137 if (BO->getOpcode() == BO_Assign) {
8139 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8140 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8142 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8144 return setLCDeclAndLB(DRE->
getDecl(), DRE, BO->getRHS(), EmitDiags);
8146 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8147 if (ME->isArrow() &&
8148 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8149 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8153 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8154 if (DS->isSingleDecl()) {
8155 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8156 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8159 SemaRef.Diag(S->getBeginLoc(),
8160 diag::ext_omp_loop_not_canonical_init)
8161 << S->getSourceRange();
8162 return setLCDeclAndLB(
8165 Var->getType().getNonReferenceType(),
8167 Var->getInit(), EmitDiags);
8171 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8172 if (CE->getOperator() == OO_Equal) {
8173 Expr *LHS = CE->getArg(0);
8174 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8175 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8177 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8179 return setLCDeclAndLB(DRE->
getDecl(), DRE, CE->getArg(1), EmitDiags);
8181 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8182 if (ME->isArrow() &&
8183 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8184 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8190 if (dependent() || SemaRef.CurContext->isDependentContext())
8193 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8194 << S->getSourceRange();
8205 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(
E))
8207 if ((Ctor->isCopyOrMoveConstructor() ||
8208 Ctor->isConvertingConstructor(
false)) &&
8209 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8211 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(
E)) {
8212 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8215 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(
E))
8216 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8221bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8228 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8230 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8231 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8237 if (!CollapsedLoopVarDecls.empty()) {
8238 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8239 if (!FSEC.TraverseStmt(S)) {
8241 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8248 auto &&CheckAndSetCond =
8253 if (getInitLCDecl(LHS) == LCDecl)
8254 return setUB(
const_cast<Expr *
>(RHS),
8256 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8257 if (getInitLCDecl(RHS) == LCDecl)
8258 return setUB(
const_cast<Expr *
>(LHS),
8260 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8261 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8262 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8266 return std::nullopt;
8268 std::optional<bool> Res;
8269 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8272 RBO->getOperatorLoc());
8273 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8274 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8275 BO->getSourceRange(), BO->getOperatorLoc());
8276 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8277 if (CE->getNumArgs() == 2) {
8278 Res = CheckAndSetCond(
8280 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8285 if (dependent() || SemaRef.CurContext->isDependentContext())
8287 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8288 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8292bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8299 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8300 if (BO->isAdditiveOp()) {
8301 bool IsAdd = BO->getOpcode() == BO_Add;
8302 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8303 return setStep(BO->getRHS(), !IsAdd);
8304 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8305 return setStep(BO->getLHS(),
false);
8307 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8308 bool IsAdd = CE->getOperator() == OO_Plus;
8309 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8310 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8311 return setStep(CE->getArg(1), !IsAdd);
8312 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8313 return setStep(CE->getArg(0),
false);
8316 if (dependent() || SemaRef.CurContext->isDependentContext())
8318 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8323bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8338 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8341 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8342 if (!ExprTemp->cleanupsHaveSideEffects())
8343 S = ExprTemp->getSubExpr();
8345 if (!CollapsedLoopVarDecls.empty()) {
8346 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8347 if (!FSEC.TraverseStmt(S)) {
8349 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8355 IncrementSrcRange = S->getSourceRange();
8356 S = S->IgnoreParens();
8357 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8358 if (UO->isIncrementDecrementOp() &&
8359 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8360 return setStep(SemaRef
8361 .ActOnIntegerConstant(UO->getBeginLoc(),
8362 (UO->isDecrementOp() ? -1 : 1))
8365 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8366 switch (BO->getOpcode()) {
8369 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8370 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8373 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8374 return checkAndSetIncRHS(BO->getRHS());
8379 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8380 switch (CE->getOperator()) {
8383 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8384 return setStep(SemaRef
8385 .ActOnIntegerConstant(
8387 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8393 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8394 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8397 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8398 return checkAndSetIncRHS(CE->getArg(1));
8404 if (dependent() || SemaRef.CurContext->isDependentContext())
8406 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8407 << S->getSourceRange() << LCDecl;
8413 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8414 StringRef Name =
".capture_expr.") {
8421 auto I = Captures.find(
Capture);
8422 if (I != Captures.end())
8435 bool TestIsStrictOp,
bool RoundToStep,
8436 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8437 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8440 llvm::APSInt LRes, SRes;
8441 bool IsLowerConst =
false, IsStepConst =
false;
8442 if (std::optional<llvm::APSInt> Res =
8445 IsLowerConst =
true;
8447 if (std::optional<llvm::APSInt> Res =
8452 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8453 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8454 (TestIsStrictOp && LRes.isStrictlyPositive()));
8455 bool NeedToReorganize =
false;
8457 if (!NoNeedToConvert && IsLowerConst &&
8458 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8459 NoNeedToConvert =
true;
8461 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8462 ? LRes.getBitWidth()
8463 : SRes.getBitWidth();
8464 LRes = LRes.extend(BW + 1);
8465 LRes.setIsSigned(
true);
8466 SRes = SRes.extend(BW + 1);
8467 SRes.setIsSigned(
true);
8469 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8470 LRes = LRes.trunc(BW);
8472 if (TestIsStrictOp) {
8473 unsigned BW = LRes.getBitWidth();
8474 LRes = LRes.extend(BW + 1);
8475 LRes.setIsSigned(
true);
8478 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8480 LRes = LRes.trunc(BW);
8482 NeedToReorganize = NoNeedToConvert;
8485 bool IsUpperConst =
false;
8486 if (std::optional<llvm::APSInt> Res =
8489 IsUpperConst =
true;
8491 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8492 (!RoundToStep || IsStepConst)) {
8493 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8494 : URes.getBitWidth();
8495 LRes = LRes.extend(BW + 1);
8496 LRes.setIsSigned(
true);
8497 URes = URes.extend(BW + 1);
8498 URes.setIsSigned(
true);
8500 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8501 NeedToReorganize = NoNeedToConvert;
8506 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8512 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8515 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8526 if (!Lower || !Upper || NewStep.
isInvalid())
8532 if (NeedToReorganize) {
8546 S, DefaultLoc, BO_Add, Diff.
get(),
8556 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8560 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8576 S, DefaultLoc, BO_Sub, Diff.
get(),
8596 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8604Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8606 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8615 if (InitDependOnLC) {
8616 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8617 if (!IS.MinValue || !IS.MaxValue)
8626 IS.CounterVar, MinValue.
get());
8631 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8646 IS.CounterVar, MaxValue.
get());
8651 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8660 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8662 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8663 if (!LBMin || !LBMax)
8667 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8671 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8675 if (*TestIsLessOp) {
8679 MinLessMax, LBMin, LBMax);
8682 LBVal = MinLB.
get();
8687 MinLessMax, LBMax, LBMin);
8690 LBVal = MaxLB.
get();
8694 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8697 LBVal = LBMinVal.
get();
8701 if (CondDependOnLC) {
8702 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8703 if (!IS.MinValue || !IS.MaxValue)
8712 IS.CounterVar, MinValue.
get());
8717 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8732 IS.CounterVar, MaxValue.
get());
8737 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
8746 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
8748 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
8749 if (!UBMin || !UBMax)
8753 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8756 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
8757 Captures,
".min_greater_max")
8761 if (*TestIsLessOp) {
8765 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8768 UBVal = MaxUB.
get();
8773 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8776 UBVal = MinUB.
get();
8779 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8780 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8781 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
8782 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
8783 if (!Upper || !Lower)
8786 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8787 Step, VarType, TestIsStrictOp,
8796 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
8799 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
8802 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
8811 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
8812 if (NewSize !=
C.getTypeSize(
Type)) {
8813 if (NewSize <
C.getTypeSize(
Type)) {
8814 assert(NewSize == 64 &&
"incorrect loop var size");
8815 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8816 << InitSrcRange << ConditionSrcRange;
8818 QualType NewType =
C.getIntTypeForBitwidth(
8820 C.getTypeSize(
Type) < NewSize);
8833std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8834 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8838 return std::make_pair(
nullptr,
nullptr);
8841 Expr *MinExpr =
nullptr;
8842 Expr *MaxExpr =
nullptr;
8843 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8844 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8846 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8848 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8850 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8852 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8853 if (!Upper || !Lower)
8854 return std::make_pair(
nullptr,
nullptr);
8864 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8865 Step, VarType, TestIsStrictOp,
8868 return std::make_pair(
nullptr,
nullptr);
8874 return std::make_pair(
nullptr,
nullptr);
8876 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8878 return std::make_pair(
nullptr,
nullptr);
8879 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
8881 return std::make_pair(
nullptr,
nullptr);
8886 return std::make_pair(
nullptr,
nullptr);
8898 return std::make_pair(
nullptr,
nullptr);
8900 if (*TestIsLessOp) {
8904 S, DefaultLoc, BO_Add,
8908 return std::make_pair(
nullptr,
nullptr);
8913 S, DefaultLoc, BO_Sub,
8917 return std::make_pair(
nullptr,
nullptr);
8926 return std::make_pair(
nullptr,
nullptr);
8931 return std::make_pair(
nullptr,
nullptr);
8934 MaxExpr = Diff.
get();
8936 MinExpr = Diff.
get();
8938 return std::make_pair(MinExpr, MaxExpr);
8941Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
8942 if (InitDependOnLC || CondDependOnLC)
8947Expr *OpenMPIterationSpaceChecker::buildPreCond(
8949 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8954 if (CondDependOnLC || InitDependOnLC)
8965 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8966 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8972 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8973 : (TestIsStrictOp ? BO_GT : BO_GE),
8974 NewLB.
get(), NewUB.
get());
8984 return CondExpr.
isUsable() ? CondExpr.
get() : Cond;
8988DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8989 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8990 DSAStackTy &DSA)
const {
8991 auto *VD = dyn_cast<VarDecl>(LCDecl);
8996 const DSAStackTy::DSAVarData
Data =
8997 DSA.getTopDSA(LCDecl,
false);
9001 Captures.insert(std::make_pair(LCRef, Ref));
9004 return cast<DeclRefExpr>(LCRef);
9007Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9013 isa<VarDecl>(LCDecl)
9024Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9027Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9029Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9037 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9038 "Expected only + or - operations for depend clauses.");
9050 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9052 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9053 if (!Upper || !Lower)
9057 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9058 false,
false, Captures);
9068 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9069 assert(
Init &&
"Expected loop in canonical form.");
9070 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9077 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9079 if (!ISC.checkAndSetInit(
Init,
false)) {
9081 auto *VD = dyn_cast<VarDecl>(
D);
9089 VD = cast<VarDecl>(PrivateRef->
getDecl());
9092 DSAStack->addLoopControlVariable(
D, VD);
9095 DSAStack->resetPossibleLoopCounter();
9096 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9109 DSAStackTy::DSAVarData DVar =
9113 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9116 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9119 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9122 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9124 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9126 IsOpenMPTaskloopDirective(DKind) ||
9129 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9130 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9131 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9132 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9133 << getOpenMPClauseName(PredeterminedCKind);
9134 if (DVar.RefExpr ==
nullptr)
9135 DVar.CKind = PredeterminedCKind;
9137 }
else if (LoopDeclRefExpr) {
9142 if (DVar.CKind == OMPC_unknown)
9143 DSAStack->addDSA(
D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9147 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9152class OMPDoacrossKind {
9155 return C->getDependenceType() == OMPC_DOACROSS_source ||
9156 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9159 return C->getDependenceType() == OMPC_DOACROSS_sink;
9162 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9170 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9171 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9172 Expr *OrderedLoopCountExpr,
9175 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9176 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9181 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9182 S = CanonLoop->getLoopStmt();
9183 auto *For = dyn_cast_or_null<ForStmt>(S);
9184 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9186 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9187 SemaRef.
Diag(S->getBeginLoc(), diag::err_omp_not_for)
9188 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9189 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9190 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9191 if (TotalNestedLoopCount > 1) {
9192 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9193 SemaRef.
Diag(DSA.getConstructLoc(),
9194 diag::note_omp_collapse_ordered_expr)
9197 else if (CollapseLoopCountExpr)
9199 diag::note_omp_collapse_ordered_expr)
9203 diag::note_omp_collapse_ordered_expr)
9208 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9214 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9215 For ? For->getForLoc() : CXXFor->getForLoc(),
9216 CollapsedLoopVarDecls);
9219 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9220 if (ISC.checkAndSetInit(
Init))
9223 bool HasErrors =
false;
9226 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9236 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9250 VarsWithImplicitDSA.erase(LCDecl);
9255 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9258 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9265 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9266 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9267 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9268 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9275 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9276 ISC.buildCounterVar(Captures, DSA);
9277 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9278 ISC.buildPrivateCounterVar();
9279 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9280 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9281 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9282 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9283 ISC.getConditionSrcRange();
9284 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9285 ISC.getIncrementSrcRange();
9286 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9287 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9288 ISC.isStrictTestOp();
9289 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9290 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9291 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9292 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9293 ISC.buildFinalCondition(DSA.getCurScope());
9294 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9295 ISC.doesInitDependOnLC();
9296 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9297 ISC.doesCondDependOnLC();
9298 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9299 ISC.getLoopDependentIdx();
9302 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9303 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9304 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9305 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9306 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9307 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9308 if (!HasErrors && DSA.isOrderedRegion()) {
9309 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9310 if (CurrentNestedLoopCount <
9311 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9312 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9313 CurrentNestedLoopCount,
9314 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9315 DSA.getOrderedRegionParam().second->setLoopCounter(
9316 CurrentNestedLoopCount,
9317 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9320 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9321 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9322 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9324 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9325 if (CurrentNestedLoopCount >= NumLoops) {
9329 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9330 Pair.second.size() <= CurrentNestedLoopCount) {
9332 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9335 OMPDoacrossKind ODK;
9336 if (DoacrossC && ODK.isSink(DoacrossC) &&
9337 Pair.second.size() <= CurrentNestedLoopCount) {
9339 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9344 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9345 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9346 (DoacrossC && ODK.isSource(DoacrossC)))
9347 CntValue = ISC.buildOrderedLoopData(
9349 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9351 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9354 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9362 CntValue = ISC.buildOrderedLoopData(
9364 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9365 DepLoc, Inc, clang::OO_Minus);
9367 CntValue = ISC.buildOrderedLoopData(
9369 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9370 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9371 Pair.second[CurrentNestedLoopCount].second);
9373 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9375 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9386 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9390 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9411 bool IsNonRectangularLB,
9412 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9421 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9436 if (Captures && !IsNonRectangularLB)
9437 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9446 Update.get()->getType()->isOverloadableType()) {
9453 SemaRef.
BuildBinOp(S,
Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9454 VarRef.
get(), SavedUpdate.
get());
9465 NewStart.
get(), SavedUpdate.
get());
9489 unsigned HasBits =
C.getTypeSize(OldType);
9490 if (HasBits >= Bits)
9493 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9503 if (std::optional<llvm::APSInt>
Result =
9512 if (!PreInits.empty()) {
9533 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9542 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9543 if (!Captures.empty()) {
9545 for (
const auto &Pair : Captures)
9546 PreInits.push_back(Pair.second->getDecl());
9554 if (PreInits.empty())
9558 for (
Stmt *S : PreInits)
9565 Expr *PostUpdate =
nullptr;
9566 if (!PostUpdates.empty()) {
9567 for (
Expr *
E : PostUpdates) {
9573 PostUpdate = PostUpdate
9587 int NestingDepth = 0;
9588 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9610 if (NestingDepth > 0)
9621 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9625 unsigned NestedLoopCount = 1;
9626 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9630 if (CollapseLoopCountExpr) {
9635 NestedLoopCount =
Result.Val.getInt().getLimitedValue();
9638 FVDF.TraverseStmt(AStmt);
9644 unsigned OrderedLoopCount = 1;
9645 if (OrderedLoopCountExpr) {
9652 if (
Result.getLimitedValue() < NestedLoopCount) {
9654 diag::err_omp_wrong_ordered_loop_count)
9657 diag::note_collapse_loop_count)
9660 OrderedLoopCount =
Result.getLimitedValue();
9668 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9669 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9673 SupportsNonPerfectlyNested, NumLoops,
9674 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9675 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9676 &IterSpaces, &Captures,
9677 &CollapsedLoopVarDecls](
unsigned Cnt,
Stmt *CurStmt) {
9679 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9680 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9681 VarsWithImplicitDSA, IterSpaces, Captures,
9682 CollapsedLoopVarDecls))
9684 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9685 IterSpaces[Cnt].CounterVar) {
9687 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9688 if (isa<OMPCapturedExprDecl>(DRE->
getDecl())) {
9689 Captures[DRE] = DRE;
9695 Stmt *DependentPreInits = Transform->getPreInits();
9696 if (!DependentPreInits)
9703 for (
Stmt *S : Constituents) {
9704 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9705 for (
Decl *
C : DC->decls()) {
9706 auto *
D = cast<VarDecl>(
C);
9708 SemaRef,
D,
D->getType().getNonReferenceType(),
9710 Captures[Ref] = Ref;
9717 Built.
clear(NestedLoopCount);
9720 return NestedLoopCount;
9753 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
9754 Expr *N0 = IterSpaces[0].NumIterations;
9758 .PerformImplicitConversion(
9773 return NestedLoopCount;
9776 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
9778 Scope *CurScope = DSA.getCurScope();
9779 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9780 if (PreCond.isUsable()) {
9782 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9783 PreCond.get(), IterSpaces[Cnt].PreCond);
9785 Expr *N = IterSpaces[Cnt].NumIterations;
9787 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
9790 CurScope,
Loc, BO_Mul, LastIteration32.
get(),
9798 CurScope,
Loc, BO_Mul, LastIteration64.
get(),
9808 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
9810 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
9811 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9815 LastIteration64.
get(), SemaRef))))
9816 LastIteration = LastIteration32;
9835 LastIteration.
get(),
9847 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
9848 LastIteration = SaveRef;
9861 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9890 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
9899 UB.
get(), LastIteration.
get());
9902 LastIteration.
get(), UB.
get());
9903 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
9928 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
9931 LastIteration.
get(), CombUB.
get());
9932 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
9937 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9941 "Unexpected number of parameters in loop combined directive");
9982 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
9988 bool UseStrictCompare =
9990 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
9991 return LIS.IsStrictCompare;
9997 if (UseStrictCompare) {
10000 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10012 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10015 NumIterations.
get());
10018 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10019 NumIterations.
get());
10024 Expr *BoundCombUB = CombUB.
get();
10025 if (UseStrictCompare) {
10029 CurScope, CondLoc, BO_Add, BoundCombUB,
10037 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10038 IV.
get(), BoundCombUB);
10045 if (!Inc.isUsable())
10047 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10049 if (!Inc.isUsable())
10056 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10062 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10073 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10089 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10101 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10115 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10118 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10119 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10123 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10124 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10128 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10139 DistEUBLoc, NewPrevUB.
get());
10144 UB.
get(), NewPrevUB.
get());
10146 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10147 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10155 Expr *BoundPrevUB = PrevUB.
get();
10156 if (UseStrictCompare) {
10160 CurScope, CondLoc, BO_Add, BoundPrevUB,
10168 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10169 IV.
get(), BoundPrevUB);
10173 bool HasErrors =
false;
10174 Built.
Counters.resize(NestedLoopCount);
10175 Built.
Inits.resize(NestedLoopCount);
10176 Built.
Updates.resize(NestedLoopCount);
10177 Built.
Finals.resize(NestedLoopCount);
10198 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10199 LoopIterationSpace &IS = IterSpaces[Cnt];
10205 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10206 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10207 IterSpaces[K].NumIterations);
10212 if (Cnt + 1 < NestedLoopCount)
10217 if (!
Iter.isUsable()) {
10226 if (Cnt + 1 < NestedLoopCount)
10231 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10234 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10236 SemaRef, VD, IS.CounterVar->
getType(), IS.CounterVar->getExprLoc(),
10240 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10241 if (!
Init.isUsable()) {
10246 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
Iter,
10247 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10248 if (!
Update.isUsable()) {
10256 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10257 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10258 if (!Final.isUsable()) {
10263 if (!
Update.isUsable() || !Final.isUsable()) {
10268 Built.
Counters[Cnt] = IS.CounterVar;
10272 Built.
Finals[Cnt] = Final.get();
10276 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10295 Built.
PreCond = PreCond.get();
10299 Built.
Inc = Inc.get();
10300 Built.
LB = LB.
get();
10301 Built.
UB = UB.
get();
10302 Built.
IL = IL.
get();
10303 Built.
ST = ST.
get();
10305 Built.
NLB = NextLB.
get();
10306 Built.
NUB = NextUB.
get();
10321 return NestedLoopCount;
10325 auto CollapseClauses =
10326 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10327 if (CollapseClauses.begin() != CollapseClauses.end())
10328 return (*CollapseClauses.begin())->getNumForLoops();
10333 auto OrderedClauses =
10334 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10335 if (OrderedClauses.begin() != OrderedClauses.end())
10336 return (*OrderedClauses.begin())->getNumForLoops();
10345 for (
const OMPClause *Clause : Clauses) {
10347 Safelen = cast<OMPSafelenClause>(Clause);
10349 Simdlen = cast<OMPSimdlenClause>(Clause);
10350 if (Safelen && Simdlen)
10354 if (Simdlen && Safelen) {
10368 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10369 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10374 if (SimdlenRes > SafelenRes) {
10376 diag::err_omp_wrong_simdlen_safelen_values)
10392 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10399 if (NestedLoopCount == 0)
10409 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10410 return SimdDirective;
10419 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10426 if (NestedLoopCount == 0)
10433 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10435 return ForDirective;
10446 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10450 unsigned NestedLoopCount =
10453 VarsWithImplicitDSA, B);
10454 if (NestedLoopCount == 0)
10464 NestedLoopCount, Clauses, AStmt, B);
10468 Stmt *AStmt, DSAStackTy *Stack) {
10472 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10473 auto BaseStmt = AStmt;
10474 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10476 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10477 auto S =
C->children();
10478 if (S.begin() == S.end())
10482 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10483 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10485 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10486 diag::err_omp_sections_substmt_not_section)
10487 << getOpenMPDirectiveName(DKind);
10490 cast<OMPSectionDirective>(SectionStmt)
10491 ->setHasCancel(Stack->isCancelRegion());
10494 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10495 << getOpenMPDirectiveName(DKind);
10530 if (
auto *CE = dyn_cast<CallExpr>(
E))
10531 if (CE->getDirectCallee())
10543 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10553 Expr *TargetCall =
nullptr;
10555 auto *
E = dyn_cast<Expr>(S);
10557 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10563 if (
auto *BO = dyn_cast<BinaryOperator>(
E)) {
10564 if (BO->getOpcode() == BO_Assign)
10567 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(
E))
10568 if (COCE->getOperator() == OO_Equal)
10583 Clauses, AStmt, TargetCallLoc);
10588 DSAStackTy *Stack) {
10589 bool ErrorFound =
false;
10591 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10592 for (
Expr *RefExpr : LPC->varlist()) {
10595 Expr *SimpleRefExpr = RefExpr;
10598 auto &&Info = Stack->isLoopControlVariable(
D);
10600 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10601 << getOpenMPDirectiveName(K);
10630 if (NestedLoopCount == 0)
10634 "omp loop exprs were not built");
10637 NestedLoopCount, Clauses, AStmt, B);
10656 unsigned NestedLoopCount =
10659 VarsWithImplicitDSA, B);
10660 if (NestedLoopCount == 0)
10664 "omp loop exprs were not built");
10666 DSAStack->setParentTeamsRegionLoc(StartLoc);
10669 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10690 unsigned NestedLoopCount =
10693 VarsWithImplicitDSA, B);
10694 if (NestedLoopCount == 0)
10698 "omp loop exprs were not built");
10701 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10723 unsigned NestedLoopCount =
10726 VarsWithImplicitDSA, B);
10727 if (NestedLoopCount == 0)
10731 "omp loop exprs were not built");
10734 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10755 unsigned NestedLoopCount =
10758 VarsWithImplicitDSA, B);
10759 if (NestedLoopCount == 0)
10763 "omp loop exprs were not built");
10766 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10776 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10783 const OMPClause *Copyprivate =
nullptr;
10784 for (
const OMPClause *Clause : Clauses) {
10788 Copyprivate = Clause;
10789 if (Copyprivate && Nowait) {
10791 diag::err_omp_single_copyprivate_with_nowait);
10831 bool ErrorFound =
false;
10834 bool DependentHint =
false;
10836 if (
C->getClauseKind() == OMPC_hint) {
10838 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10841 Expr *
E = cast<OMPHintClause>(
C)->getHint();
10844 DependentHint =
true;
10847 HintLoc =
C->getBeginLoc();
10853 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
10854 if (Pair.first && DirName.
getName() && !DependentHint) {
10855 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10856 Diag(StartLoc, diag::err_omp_critical_with_hint);
10858 Diag(HintLoc, diag::note_omp_critical_hint_here)
10859 << 0 <<
toString(Hint, 10,
false);
10861 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10862 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
10863 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
10868 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10876 EndLoc, Clauses, AStmt);
10877 if (!Pair.first && DirName.
getName() && !DependentHint)
10878 DSAStack->addCriticalWithHint(Dir, Hint);
10893 unsigned NestedLoopCount =
10896 VarsWithImplicitDSA, B);
10897 if (NestedLoopCount == 0)
10904 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10920 unsigned NestedLoopCount =
10923 VarsWithImplicitDSA, B);
10924 if (NestedLoopCount == 0)
10934 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10947 DSAStack->getTaskgroupReductionRef());
10960 DSAStack->getTaskgroupReductionRef());
10981 bool ErrorFound =
false;
10983 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
10987 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10988 << getOpenMPClauseName(
C->getClauseKind())
11010 {OMPC_detach, OMPC_mergeable}))
11016 AStmt,
DSAStack->isCancelRegion());
11032 bool InExContext) {
11034 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11036 if (AtC && !InExContext && AtC->
getAtKind() == OMPC_AT_execution) {
11042 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11044 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11047 if (!AtC || AtC->
getAtKind() == OMPC_AT_compilation) {
11048 if (SeverityC && SeverityC->
getSeverityKind() == OMPC_SEVERITY_warning)
11050 << (ME ? cast<StringLiteral>(ME)->getString() :
"WARNING");
11052 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11053 << (ME ? cast<StringLiteral>(ME)->getString() :
"ERROR");
11054 if (!SeverityC || SeverityC->
getSeverityKind() != OMPC_SEVERITY_warning)
11065 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11067 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11069 if (NowaitC && !HasDependC) {
11070 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11085 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
11091 DSAStack->getTaskgroupReductionRef());
11100 if (
C->getClauseKind() == OMPC_flush)
11101 FC = cast<OMPFlushClause>(
C);
11108 if (
C->getClauseKind() == OMPC_acq_rel ||
11109 C->getClauseKind() == OMPC_acquire ||
11110 C->getClauseKind() == OMPC_release) {
11111 if (MemOrderKind != OMPC_unknown) {
11112 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11113 << getOpenMPDirectiveName(OMPD_flush) << 1
11115 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11116 << getOpenMPClauseName(MemOrderKind);
11118 MemOrderKind =
C->getClauseKind();
11119 MemOrderLoc =
C->getBeginLoc();
11123 if (FC && OrderClause) {
11126 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11136 if (Clauses.empty()) {
11137 Diag(StartLoc, diag::err_omp_depobj_expected);
11139 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11140 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11144 if (Clauses.size() > 2) {
11145 Diag(Clauses[2]->getBeginLoc(),
11146 diag::err_omp_depobj_single_clause_expected);
11148 }
else if (Clauses.size() < 1) {
11149 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11159 if (Clauses.size() != 1) {
11160 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11161 diag::err_omp_scan_single_clause_expected);
11166 Scope *ParentS = S->getParent();
11169 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11170 << getOpenMPDirectiveName(OMPD_scan) << 5);
11174 if (
DSAStack->doesParentHasScanDirective()) {
11175 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11177 diag::note_omp_previous_directive)
11181 DSAStack->setParentHasScanDirective(StartLoc);
11189 const OMPClause *DependFound =
nullptr;
11190 const OMPClause *DependSourceClause =
nullptr;
11191 const OMPClause *DependSinkClause =
nullptr;
11192 const OMPClause *DoacrossFound =
nullptr;
11193 const OMPClause *DoacrossSourceClause =
nullptr;
11194 const OMPClause *DoacrossSinkClause =
nullptr;
11195 bool ErrorFound =
false;
11199 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11200 auto DC = dyn_cast<OMPDependClause>(
C);
11202 DependFound = DC ?
C :
nullptr;
11203 DoacrossFound = DOC ?
C :
nullptr;
11204 OMPDoacrossKind ODK;
11205 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11206 (DOC && (ODK.isSource(DOC)))) {
11207 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11208 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11209 << getOpenMPDirectiveName(OMPD_ordered)
11210 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11214 DependSourceClause =
C;
11216 DoacrossSourceClause =
C;
11218 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11219 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11220 << (DC ?
"depend" :
"doacross") << 0;
11223 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11224 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11225 if (DependSourceClause || DoacrossSourceClause) {
11226 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11227 << (DC ?
"depend" :
"doacross") << 1;
11231 DependSinkClause =
C;
11233 DoacrossSinkClause =
C;
11235 }
else if (
C->getClauseKind() == OMPC_threads) {
11236 TC = cast<OMPThreadsClause>(
C);
11237 }
else if (
C->getClauseKind() == OMPC_simd) {
11238 SC = cast<OMPSIMDClause>(
C);
11241 if (!ErrorFound && !SC &&
11246 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11249 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11252 Diag(
Loc, diag::err_omp_depend_clause_thread_simd)
11253 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11256 }
else if ((DependFound || DoacrossFound) &&
11257 !
DSAStack->getParentOrderedRegionParam().first) {
11260 Diag(
Loc, diag::err_omp_ordered_directive_without_param)
11261 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11263 }
else if (TC || Clauses.empty()) {
11264 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11266 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11267 << (TC !=
nullptr);
11272 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11280 if (!DependFound && !DoacrossFound) {
11281 if (
DSAStack->doesParentHasOrderedDirective()) {
11282 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11284 diag::note_omp_previous_directive)
11288 DSAStack->setParentHasOrderedDirective(StartLoc);
11292 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
11304class OpenMPAtomicUpdateChecker {
11306 enum ExprAnalysisErrorCode {
11310 NotABinaryOrUnaryExpression,
11312 NotAnUnaryIncDecExpression,
11318 NotABinaryExpression,
11321 NotABinaryOperator,
11324 NotAnUpdateExpression,
11327 NotAValidExpression,
11345 bool IsXLHSInRHSPart;
11350 bool IsPostfixUpdate;
11353 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11354 : SemaRef(SemaRef),
X(nullptr),
E(nullptr), UpdateExpr(nullptr),
11355 IsXLHSInRHSPart(
false), Op(BO_PtrMemD), IsPostfixUpdate(
false) {}
11363 bool checkStatement(
Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11365 Expr *getX()
const {
return X; }
11367 Expr *getExpr()
const {
return E; }
11371 Expr *getUpdateExpr()
const {
return UpdateExpr; }
11374 bool isXLHSInRHSPart()
const {
return IsXLHSInRHSPart; }
11378 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11381 bool checkBinaryOperation(
BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11382 unsigned NoteId = 0);
11385bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11386 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11387 ExprAnalysisErrorCode ErrorFound = NoError;
11393 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11395 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11397 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11398 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11399 AtomicInnerBinOp->isBitwiseOp()) {
11400 Op = AtomicInnerBinOp->getOpcode();
11401 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11402 Expr *LHS = AtomicInnerBinOp->getLHS();
11403 Expr *RHS = AtomicInnerBinOp->getRHS();
11404 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11411 if (XId == LHSId) {
11413 IsXLHSInRHSPart =
true;
11414 }
else if (XId == RHSId) {
11416 IsXLHSInRHSPart =
false;
11418 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11419 ErrorRange = AtomicInnerBinOp->getSourceRange();
11420 NoteLoc =
X->getExprLoc();
11421 NoteRange =
X->getSourceRange();
11422 ErrorFound = NotAnUpdateExpression;
11425 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11426 ErrorRange = AtomicInnerBinOp->getSourceRange();
11427 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11429 ErrorFound = NotABinaryOperator;
11434 ErrorFound = NotABinaryExpression;
11441 ErrorFound = NotAnAssignmentOp;
11443 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11444 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11445 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11449 E =
X = UpdateExpr =
nullptr;
11450 return ErrorFound != NoError;
11453bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11455 ExprAnalysisErrorCode ErrorFound = NoError;
11466 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11467 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11468 if (AtomicBody->getType()->isScalarType() ||
11469 AtomicBody->isInstantiationDependent()) {
11470 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11471 AtomicBody->IgnoreParenImpCasts())) {
11474 AtomicCompAssignOp->getOpcode());
11475 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11476 E = AtomicCompAssignOp->getRHS();
11477 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11478 IsXLHSInRHSPart =
true;
11479 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11480 AtomicBody->IgnoreParenImpCasts())) {
11482 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11484 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11485 AtomicBody->IgnoreParenImpCasts())) {
11487 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11488 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11489 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11490 OpLoc = AtomicUnaryOp->getOperatorLoc();
11491 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11493 IsXLHSInRHSPart =
true;
11495 ErrorFound = NotAnUnaryIncDecExpression;
11496 ErrorLoc = AtomicUnaryOp->getExprLoc();
11497 ErrorRange = AtomicUnaryOp->getSourceRange();
11498 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11501 }
else if (!AtomicBody->isInstantiationDependent()) {
11502 ErrorFound = NotABinaryOrUnaryExpression;
11503 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11504 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11505 }
else if (AtomicBody->containsErrors()) {
11506 ErrorFound = NotAValidExpression;
11507 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11508 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11511 ErrorFound = NotAScalarType;
11512 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11513 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11516 ErrorFound = NotAnExpression;
11517 NoteLoc = ErrorLoc = S->getBeginLoc();
11518 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11520 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11521 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11522 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11526 E =
X = UpdateExpr =
nullptr;
11527 if (ErrorFound == NoError &&
E &&
X) {
11537 IsXLHSInRHSPart ? OVEExpr : OVEX);
11544 UpdateExpr =
Update.get();
11546 return ErrorFound != NoError;
11550llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11551 llvm::FoldingSetNodeID
Id;
11552 S->IgnoreParenImpCasts()->Profile(
Id, Context,
true);
11557bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11559 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11562class OpenMPAtomicCompareChecker {
11609 struct ErrorInfoTy {
11617 OpenMPAtomicCompareChecker(
Sema &S) : ContextRef(S.getASTContext()) {}
11620 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11622 Expr *getX()
const {
return X; }
11623 Expr *getE()
const {
return E; }
11624 Expr *getD()
const {
return D; }
11625 Expr *getCond()
const {
return C; }
11626 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11645 bool IsXBinopExpr =
true;
11648 bool checkCondUpdateStmt(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11651 bool checkCondExprStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11654 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11656 static bool CheckValue(
const Expr *
E, ErrorInfoTy &ErrorInfo,
11657 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11661 if (ShouldBeLValue && !
E->
isLValue()) {
11662 ErrorInfo.Error = ErrorTy::XNotLValue;
11663 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11670 ErrorInfo.Error = ErrorTy::NotScalar;
11671 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11676 ErrorInfo.Error = ErrorTy::NotInteger;
11677 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11686bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11687 ErrorInfoTy &ErrorInfo) {
11688 auto *Then = S->getThen();
11689 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11690 if (CS->body_empty()) {
11691 ErrorInfo.Error = ErrorTy::NoStmt;
11692 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11693 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11696 if (CS->size() > 1) {
11697 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11698 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11699 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11702 Then = CS->body_front();
11705 auto *BO = dyn_cast<BinaryOperator>(Then);
11707 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11708 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11709 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11712 if (BO->getOpcode() != BO_Assign) {
11713 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11714 ErrorInfo.ErrorLoc = BO->getExprLoc();
11715 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11716 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11722 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11724 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11725 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11726 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11730 switch (Cond->getOpcode()) {
11734 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11735 E = Cond->getRHS();
11736 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11737 E = Cond->getLHS();
11739 ErrorInfo.Error = ErrorTy::InvalidComparison;
11740 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11741 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11749 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS()) &&
11750 checkIfTwoExprsAreSame(ContextRef,
E, Cond->getRHS())) {
11752 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, Cond->getLHS()) &&
11753 checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11755 IsXBinopExpr =
false;
11757 ErrorInfo.Error = ErrorTy::InvalidComparison;
11758 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11759 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11765 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11766 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11767 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11771 if (S->getElse()) {
11772 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11773 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11774 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11781bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
11782 ErrorInfoTy &ErrorInfo) {
11783 auto *BO = dyn_cast<BinaryOperator>(S);
11785 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11786 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11787 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11790 if (BO->getOpcode() != BO_Assign) {
11791 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11792 ErrorInfo.ErrorLoc = BO->getExprLoc();
11793 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11794 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11800 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11802 ErrorInfo.Error = ErrorTy::NotCondOp;
11803 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11804 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11808 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
11809 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11810 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11811 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11812 CO->getFalseExpr()->getSourceRange();
11816 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11818 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11819 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11820 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11821 CO->getCond()->getSourceRange();
11825 switch (Cond->getOpcode()) {
11828 D = CO->getTrueExpr();
11829 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11830 E = Cond->getRHS();
11831 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11832 E = Cond->getLHS();
11834 ErrorInfo.Error = ErrorTy::InvalidComparison;
11835 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11836 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11843 E = CO->getTrueExpr();
11844 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS()) &&
11845 checkIfTwoExprsAreSame(ContextRef,
E, Cond->getRHS())) {
11847 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, Cond->getLHS()) &&
11848 checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11850 IsXBinopExpr =
false;
11852 ErrorInfo.Error = ErrorTy::InvalidComparison;
11853 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11854 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11860 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11861 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11862 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11869bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
11871 assert(
X &&
E &&
"X and E cannot be nullptr");
11873 if (!CheckValue(
X, ErrorInfo,
true))
11876 if (!CheckValue(
E, ErrorInfo,
false))
11879 if (
D && !CheckValue(
D, ErrorInfo,
false))
11885bool OpenMPAtomicCompareChecker::checkStmt(
11886 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11887 auto *CS = dyn_cast<CompoundStmt>(S);
11889 if (CS->body_empty()) {
11890 ErrorInfo.Error = ErrorTy::NoStmt;
11891 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11892 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11896 if (CS->size() != 1) {
11897 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11898 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11899 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11902 S = CS->body_front();
11907 if (
auto *IS = dyn_cast<IfStmt>(S)) {
11913 Res = checkCondUpdateStmt(IS, ErrorInfo);
11919 Res = checkCondExprStmt(S, ErrorInfo);
11925 return checkType(ErrorInfo);
11928class OpenMPAtomicCompareCaptureChecker final
11929 :
public OpenMPAtomicCompareChecker {
11931 OpenMPAtomicCompareCaptureChecker(
Sema &S) : OpenMPAtomicCompareChecker(S) {}
11933 Expr *getV()
const {
return V; }
11934 Expr *getR()
const {
return R; }
11935 bool isFailOnly()
const {
return IsFailOnly; }
11936 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11939 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11942 bool checkType(ErrorInfoTy &ErrorInfo);
11954 bool checkForm3(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11958 bool checkForm45(
Stmt *S, ErrorInfoTy &ErrorInfo);
11965 bool IsFailOnly =
false;
11967 bool IsPostfixUpdate =
false;
11970bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11971 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11974 if (
V && !CheckValue(
V, ErrorInfo,
true))
11977 if (R && !CheckValue(R, ErrorInfo,
true,
true))
11983bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
11984 ErrorInfoTy &ErrorInfo) {
11987 auto *Then = S->getThen();
11988 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11989 if (CS->body_empty()) {
11990 ErrorInfo.Error = ErrorTy::NoStmt;
11991 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11992 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11995 if (CS->size() > 1) {
11996 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11997 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11998 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12001 Then = CS->body_front();
12004 auto *BO = dyn_cast<BinaryOperator>(Then);
12006 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12007 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12008 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12011 if (BO->getOpcode() != BO_Assign) {
12012 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12013 ErrorInfo.ErrorLoc = BO->getExprLoc();
12014 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12015 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12022 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12024 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12025 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12026 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12029 if (Cond->getOpcode() != BO_EQ) {
12030 ErrorInfo.Error = ErrorTy::NotEQ;
12031 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
12032 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
12036 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
12037 E = Cond->getRHS();
12038 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
12039 E = Cond->getLHS();
12041 ErrorInfo.Error = ErrorTy::InvalidComparison;
12042 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
12043 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
12049 if (!S->getElse()) {
12050 ErrorInfo.Error = ErrorTy::NoElse;
12051 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12052 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12056 auto *Else = S->getElse();
12057 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12058 if (CS->body_empty()) {
12059 ErrorInfo.Error = ErrorTy::NoStmt;
12060 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12061 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12064 if (CS->size() > 1) {
12065 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12066 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12067 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12070 Else = CS->body_front();
12073 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12075 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12080 if (ElseBO->getOpcode() != BO_Assign) {
12081 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12082 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12083 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12084 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12088 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12089 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12090 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12092 ElseBO->getRHS()->getSourceRange();
12096 V = ElseBO->getLHS();
12098 return checkType(ErrorInfo);
12101bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12102 ErrorInfoTy &ErrorInfo) {
12105 auto *CS = cast<CompoundStmt>(S);
12106 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12107 auto *S1 = cast<BinaryOperator>(CS->body_front());
12108 auto *S2 = cast<IfStmt>(CS->body_back());
12109 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12111 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12112 ErrorInfo.Error = ErrorTy::InvalidCondition;
12113 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12114 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12120 auto *Then = S2->getThen();
12121 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12122 if (ThenCS->body_empty()) {
12123 ErrorInfo.Error = ErrorTy::NoStmt;
12124 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12125 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12128 if (ThenCS->size() > 1) {
12129 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12130 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12131 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12134 Then = ThenCS->body_front();
12137 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12139 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12140 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12141 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12144 if (ThenBO->getOpcode() != BO_Assign) {
12145 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12146 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12147 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12148 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12152 X = ThenBO->getLHS();
12153 D = ThenBO->getRHS();
12155 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12156 if (BO->getOpcode() != BO_EQ) {
12157 ErrorInfo.Error = ErrorTy::NotEQ;
12158 ErrorInfo.ErrorLoc = BO->getExprLoc();
12159 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12160 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12166 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12168 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12171 ErrorInfo.Error = ErrorTy::InvalidComparison;
12172 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->
getExprLoc();
12173 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12177 if (S2->getElse()) {
12180 auto *Else = S2->getElse();
12181 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12182 if (ElseCS->body_empty()) {
12183 ErrorInfo.Error = ErrorTy::NoStmt;
12184 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12185 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12188 if (ElseCS->size() > 1) {
12189 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12190 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12191 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12194 Else = ElseCS->body_front();
12197 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12199 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12200 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12201 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12204 if (ElseBO->getOpcode() != BO_Assign) {
12205 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12206 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12207 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12208 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12211 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12212 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12213 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12214 ErrorInfo.NoteLoc =
X->getExprLoc();
12215 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12216 ErrorInfo.NoteRange =
X->getSourceRange();
12220 V = ElseBO->getLHS();
12223 return checkType(ErrorInfo);
12226bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12227 ErrorInfoTy &ErrorInfo) {
12229 if (
auto *IS = dyn_cast<IfStmt>(S))
12230 return checkForm3(IS, ErrorInfo);
12232 auto *CS = dyn_cast<CompoundStmt>(S);
12234 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12235 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12236 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12239 if (CS->body_empty()) {
12240 ErrorInfo.Error = ErrorTy::NoStmt;
12241 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12242 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12247 if (CS->size() == 1) {
12248 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12250 ErrorInfo.Error = ErrorTy::NotIfStmt;
12251 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12252 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12257 return checkForm3(IS, ErrorInfo);
12258 }
else if (CS->size() == 2) {
12259 auto *S1 = CS->body_front();
12260 auto *S2 = CS->body_back();
12262 Stmt *UpdateStmt =
nullptr;
12263 Stmt *CondUpdateStmt =
nullptr;
12264 Stmt *CondExprStmt =
nullptr;
12266 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12272 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12273 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12275 if (isa<IfStmt>(S2))
12276 return checkForm45(CS, ErrorInfo);
12281 IsPostfixUpdate =
true;
12283 if (isa<IfStmt>(S2)) {
12285 CondUpdateStmt = S2;
12294 CondUpdateStmt = S1;
12297 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12298 auto *IS = dyn_cast<IfStmt>(CUS);
12300 ErrorInfo.Error = ErrorTy::NotIfStmt;
12301 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12302 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12306 return checkCondUpdateStmt(IS, ErrorInfo);
12310 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12311 auto *BO = dyn_cast<BinaryOperator>(US);
12313 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12314 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12315 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12318 if (BO->getOpcode() != BO_Assign) {
12319 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12320 ErrorInfo.ErrorLoc = BO->getExprLoc();
12321 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12322 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12325 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12326 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12327 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12329 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12334 this->V = BO->getLHS();
12339 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12341 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12343 if (!CheckUpdateStmt(UpdateStmt))
12346 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12347 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12348 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12352 return checkType(ErrorInfo);
12362 DSAStack->addAtomicDirectiveLoc(StartLoc);
12375 bool MutexClauseEncountered =
false;
12376 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12378 switch (
C->getClauseKind()) {
12382 MutexClauseEncountered =
true;
12385 case OMPC_compare: {
12386 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12387 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12389 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12390 << getOpenMPClauseName(AtomicKind);
12392 AtomicKind =
C->getClauseKind();
12393 AtomicKindLoc =
C->getBeginLoc();
12394 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12395 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12397 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12398 << getOpenMPClauseName(AtomicKind);
12405 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12406 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12407 << getOpenMPClauseName(
C->getClauseKind())
12417 case OMPC_relaxed: {
12418 if (MemOrderKind != OMPC_unknown) {
12419 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12420 << getOpenMPDirectiveName(OMPD_atomic) << 0
12422 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12423 << getOpenMPClauseName(MemOrderKind);
12425 MemOrderKind =
C->getClauseKind();
12426 MemOrderLoc =
C->getBeginLoc();
12434 llvm_unreachable(
"unknown clause is encountered");
12437 bool IsCompareCapture =
false;
12438 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12439 EncounteredAtomicKinds.contains(OMPC_capture)) {
12440 IsCompareCapture =
true;
12441 AtomicKind = OMPC_compare;
12450 if ((AtomicKind == OMPC_read &&
12451 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12452 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12453 AtomicKind == OMPC_unknown) &&
12454 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12456 if (AtomicKind == OMPC_unknown)
12458 Diag(
Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12459 << getOpenMPClauseName(AtomicKind)
12460 << (AtomicKind == OMPC_unknown ? 1 : 0)
12461 << getOpenMPClauseName(MemOrderKind);
12462 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12463 << getOpenMPClauseName(MemOrderKind);
12466 Stmt *Body = AStmt;
12467 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12468 Body = EWC->getSubExpr();
12473 Expr *UE =
nullptr;
12475 Expr *CE =
nullptr;
12477 bool IsXLHSInRHSPart =
false;
12478 bool IsPostfixUpdate =
false;
12479 bool IsFailOnly =
false;
12502 if (AtomicKind == OMPC_read) {
12509 } ErrorFound = NoError;
12514 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12515 const auto *AtomicBinOp =
12516 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12517 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12520 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12521 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12522 if (!
X->isLValue() || !
V->isLValue()) {
12523 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12524 ErrorFound = NotAnLValue;
12530 }
else if (!
X->isInstantiationDependent() ||
12531 !
V->isInstantiationDependent()) {
12532 const Expr *NotScalarExpr =
12533 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12536 ErrorFound = NotAScalarType;
12542 }
else if (!AtomicBody->isInstantiationDependent()) {
12543 ErrorFound = NotAnAssignmentOp;
12544 ErrorLoc = AtomicBody->getExprLoc();
12545 ErrorRange = AtomicBody->getSourceRange();
12547 : AtomicBody->getExprLoc();
12549 : AtomicBody->getSourceRange();
12552 ErrorFound = NotAnExpression;
12554 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12556 if (ErrorFound != NoError) {
12557 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12559 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12560 << ErrorFound << NoteRange;
12565 }
else if (AtomicKind == OMPC_write) {
12572 } ErrorFound = NoError;
12577 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12578 const auto *AtomicBinOp =
12579 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12580 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12583 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12585 if (!
X->isLValue()) {
12586 ErrorFound = NotAnLValue;
12589 NoteLoc =
X->getExprLoc();
12590 NoteRange =
X->getSourceRange();
12592 }
else if (!
X->isInstantiationDependent() ||
12594 const Expr *NotScalarExpr =
12595 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12598 ErrorFound = NotAScalarType;
12604 }
else if (!AtomicBody->isInstantiationDependent()) {
12605 ErrorFound = NotAnAssignmentOp;
12606 ErrorLoc = AtomicBody->getExprLoc();
12607 ErrorRange = AtomicBody->getSourceRange();
12609 : AtomicBody->getExprLoc();
12611 : AtomicBody->getSourceRange();
12614 ErrorFound = NotAnExpression;
12616 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12618 if (ErrorFound != NoError) {
12619 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12621 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12622 << ErrorFound << NoteRange;
12627 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12636 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12637 if (Checker.checkStatement(
12639 (AtomicKind == OMPC_update)
12640 ? diag::err_omp_atomic_update_not_expression_statement
12641 : diag::err_omp_atomic_not_expression_statement,
12642 diag::note_omp_atomic_update))
12645 E = Checker.getExpr();
12646 X = Checker.getX();
12647 UE = Checker.getUpdateExpr();
12648 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12650 }
else if (AtomicKind == OMPC_capture) {
12653 NotACompoundStatement,
12654 NotTwoSubstatements,
12655 NotASpecificExpression,
12657 } ErrorFound = NoError;
12660 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12669 const auto *AtomicBinOp =
12670 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12671 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12674 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12675 if (Checker.checkStatement(
12676 Body, diag::err_omp_atomic_capture_not_expression_statement,
12677 diag::note_omp_atomic_update))
12679 E = Checker.getExpr();
12680 X = Checker.getX();
12681 UE = Checker.getUpdateExpr();
12682 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12683 IsPostfixUpdate = Checker.isPostfixUpdate();
12684 }
else if (!AtomicBody->isInstantiationDependent()) {
12685 ErrorLoc = AtomicBody->getExprLoc();
12686 ErrorRange = AtomicBody->getSourceRange();
12688 : AtomicBody->getExprLoc();
12690 : AtomicBody->getSourceRange();
12691 ErrorFound = NotAnAssignmentOp;
12693 if (ErrorFound != NoError) {
12694 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12696 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12700 UE =
V =
E =
X =
nullptr;
12718 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
12720 if (CS->size() == 2) {
12722 Stmt *Second = CS->body_back();
12723 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
12724 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12725 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12726 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12728 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12729 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12731 if (IsUpdateExprFound) {
12732 BinOp = dyn_cast<BinaryOperator>(
First);
12733 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12745 llvm::FoldingSetNodeID XId, PossibleXId;
12746 Checker.getX()->
Profile(XId, Context,
true);
12747 PossibleX->
Profile(PossibleXId, Context,
true);
12748 IsUpdateExprFound = XId == PossibleXId;
12749 if (IsUpdateExprFound) {
12751 X = Checker.getX();
12752 E = Checker.getExpr();
12753 UE = Checker.getUpdateExpr();
12754 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12755 IsPostfixUpdate =
true;
12758 if (!IsUpdateExprFound) {
12759 IsUpdateExprFound = !Checker.checkStatement(
First);
12761 if (IsUpdateExprFound) {
12762 BinOp = dyn_cast<BinaryOperator>(Second);
12763 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12765 if (IsUpdateExprFound &&
12776 llvm::FoldingSetNodeID XId, PossibleXId;
12777 Checker.getX()->
Profile(XId, Context,
true);
12778 PossibleX->
Profile(PossibleXId, Context,
true);
12779 IsUpdateExprFound = XId == PossibleXId;
12780 if (IsUpdateExprFound) {
12782 X = Checker.getX();
12783 E = Checker.getExpr();
12784 UE = Checker.getUpdateExpr();
12785 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12786 IsPostfixUpdate =
false;
12790 if (!IsUpdateExprFound) {
12792 auto *FirstExpr = dyn_cast<Expr>(
First);
12793 auto *SecondExpr = dyn_cast<Expr>(Second);
12794 if (!FirstExpr || !SecondExpr ||
12795 !(FirstExpr->isInstantiationDependent() ||
12796 SecondExpr->isInstantiationDependent())) {
12797 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
12798 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12799 ErrorFound = NotAnAssignmentOp;
12800 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12801 :
First->getBeginLoc();
12802 NoteRange = ErrorRange = FirstBinOp
12803 ? FirstBinOp->getSourceRange()
12806 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12807 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12808 ErrorFound = NotAnAssignmentOp;
12809 NoteLoc = ErrorLoc = SecondBinOp
12810 ? SecondBinOp->getOperatorLoc()
12812 NoteRange = ErrorRange =
12813 SecondBinOp ? SecondBinOp->getSourceRange()
12816 Expr *PossibleXRHSInFirst =
12818 Expr *PossibleXLHSInSecond =
12820 llvm::FoldingSetNodeID X1Id, X2Id;
12821 PossibleXRHSInFirst->
Profile(X1Id, Context,
12823 PossibleXLHSInSecond->
Profile(X2Id, Context,
12825 IsUpdateExprFound = X1Id == X2Id;
12826 if (IsUpdateExprFound) {
12827 V = FirstBinOp->getLHS();
12828 X = SecondBinOp->getLHS();
12829 E = SecondBinOp->getRHS();
12831 IsXLHSInRHSPart =
false;
12832 IsPostfixUpdate =
true;
12834 ErrorFound = NotASpecificExpression;
12835 ErrorLoc = FirstBinOp->getExprLoc();
12836 ErrorRange = FirstBinOp->getSourceRange();
12837 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12838 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12846 NoteRange = ErrorRange =
12848 ErrorFound = NotTwoSubstatements;
12852 NoteRange = ErrorRange =
12854 ErrorFound = NotACompoundStatement;
12857 if (ErrorFound != NoError) {
12858 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12860 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12864 UE =
V =
E =
X =
nullptr;
12865 }
else if (AtomicKind == OMPC_compare) {
12866 if (IsCompareCapture) {
12867 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12868 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
12869 if (!Checker.checkStmt(Body, ErrorInfo)) {
12870 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12871 << ErrorInfo.ErrorRange;
12872 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12873 << ErrorInfo.Error << ErrorInfo.NoteRange;
12876 X = Checker.getX();
12877 E = Checker.getE();
12878 D = Checker.getD();
12879 CE = Checker.getCond();
12880 V = Checker.getV();
12881 R = Checker.getR();
12883 IsXLHSInRHSPart = Checker.isXBinopExpr();
12884 IsFailOnly = Checker.isFailOnly();
12885 IsPostfixUpdate = Checker.isPostfixUpdate();
12887 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12888 OpenMPAtomicCompareChecker Checker(
SemaRef);
12889 if (!Checker.checkStmt(Body, ErrorInfo)) {
12890 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12891 << ErrorInfo.ErrorRange;
12892 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12893 << ErrorInfo.Error << ErrorInfo.NoteRange;
12896 X = Checker.getX();
12897 E = Checker.getE();
12898 D = Checker.getD();
12899 CE = Checker.getCond();
12905 auto *It = find_if(Clauses, [](
OMPClause *
C) {
12906 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12908 if (It != Clauses.end()) {
12909 auto *Cond = dyn_cast<BinaryOperator>(CE);
12910 if (Cond->getOpcode() != BO_EQ) {
12911 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12913 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12914 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
12916 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12917 << ErrorInfo.ErrorRange;
12922 IsXLHSInRHSPart = Checker.isXBinopExpr();
12929 Context, StartLoc, EndLoc, Clauses, AStmt,
12930 {
X,
V, R,
E, UE,
D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12946 if (
DSAStack->hasInnerTeamsRegion()) {
12948 bool OMPTeamsFound =
true;
12949 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
12950 auto I = CS->body_begin();
12951 while (I != CS->body_end()) {
12952 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12954 if (!IsTeams || I != CS->body_begin()) {
12955 OMPTeamsFound =
false;
12956 if (IsTeams && I != CS->body_begin()) {
12965 assert(I != CS->body_end() &&
"Not found statement");
12968 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12971 if (!OMPTeamsFound) {
12972 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12974 diag::note_omp_nested_teams_construct_here);
12975 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12976 << isa<OMPExecutableDirective>(S);
13010 unsigned NestedLoopCount =
13013 VarsWithImplicitDSA, B);
13014 if (NestedLoopCount == 0)
13021 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13028 return llvm::any_of(
13029 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13032template <
typename... Params>
13034 const Params... ClauseTypes) {
13041 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13042 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13043 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13044 (VD->isExternallyVisible() &&
13045 VD->getVisibility() != HiddenVisibility);
13047 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13048 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13049 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13050 (VD->isExternallyVisible() &&
13051 VD->getVisibility() != HiddenVisibility);
13065 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13070 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13072 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13075 Expected =
"'map' or 'use_device_ptr'";
13077 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13078 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13079 <<
Expected << getOpenMPDirectiveName(OMPD_target_data);
13100 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13101 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13120 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13121 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13137 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13138 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13143 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13153template <
typename ClauseType>
13156 unsigned MaxNum,
unsigned Diag) {
13157 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13158 if (ClauseItr == Clauses.end())
13160 const auto *
C = cast<ClauseType>(*ClauseItr);
13161 auto VarList =
C->getVarRefs();
13162 if (VarList.size() > MaxNum) {
13163 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13164 << getOpenMPClauseName(
C->getClauseKind());
13177 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13178 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13179 !checkNumExprsInClause<OMPThreadLimitClause>(
13180 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13185 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13189 DSAStack->setParentTeamsRegionLoc(StartLoc);
13198 if (
DSAStack->isParentNowaitRegion()) {
13199 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13202 if (
DSAStack->isParentOrderedRegion()) {
13203 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13207 EndLoc, CancelRegion);
13213 if (
DSAStack->isParentNowaitRegion()) {
13214 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13217 if (
DSAStack->isParentOrderedRegion()) {
13218 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13221 DSAStack->setParentCancelRegion(
true);
13228 const OMPClause *ReductionClause =
nullptr;
13229 const OMPClause *NogroupClause =
nullptr;
13231 if (
C->getClauseKind() == OMPC_reduction) {
13232 ReductionClause =
C;
13237 if (
C->getClauseKind() == OMPC_nogroup) {
13239 if (ReductionClause)
13244 if (ReductionClause && NogroupClause) {
13245 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13259 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13263 unsigned NestedLoopCount =
13266 *
DSAStack, VarsWithImplicitDSA, B);
13267 if (NestedLoopCount == 0)
13271 "omp for loop exprs were not built");
13277 {OMPC_grainsize, OMPC_num_tasks}))
13287 NestedLoopCount, Clauses, AStmt, B,
13300 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13304 unsigned NestedLoopCount =
13307 VarsWithImplicitDSA, B);
13308 if (NestedLoopCount == 0)
13318 {OMPC_grainsize, OMPC_num_tasks}))
13329 NestedLoopCount, Clauses, AStmt, B);
13338 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13342 unsigned NestedLoopCount =
13345 *
DSAStack, VarsWithImplicitDSA, B);
13346 if (NestedLoopCount == 0)
13350 "omp for loop exprs were not built");
13356 {OMPC_grainsize, OMPC_num_tasks}))
13366 NestedLoopCount, Clauses, AStmt, B,
13376 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13380 unsigned NestedLoopCount =
13383 *
DSAStack, VarsWithImplicitDSA, B);
13384 if (NestedLoopCount == 0)
13388 "omp for loop exprs were not built");
13394 {OMPC_grainsize, OMPC_num_tasks}))
13404 NestedLoopCount, Clauses, AStmt, B,
13417 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13421 unsigned NestedLoopCount =
13424 VarsWithImplicitDSA, B);
13425 if (NestedLoopCount == 0)
13435 {OMPC_grainsize, OMPC_num_tasks}))
13446 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13458 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13462 unsigned NestedLoopCount =
13465 VarsWithImplicitDSA, B);
13466 if (NestedLoopCount == 0)
13476 {OMPC_grainsize, OMPC_num_tasks}))
13487 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13505 VarsWithImplicitDSA, B);
13506 if (NestedLoopCount == 0)
13510 "omp for loop exprs were not built");
13516 {OMPC_grainsize, OMPC_num_tasks}))
13525 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13544 VarsWithImplicitDSA, B);
13545 if (NestedLoopCount == 0)
13549 "omp for loop exprs were not built");
13555 {OMPC_grainsize, OMPC_num_tasks}))
13564 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13575 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13583 VarsWithImplicitDSA, B);
13584 if (NestedLoopCount == 0)
13594 {OMPC_grainsize, OMPC_num_tasks}))
13605 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13615 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13623 VarsWithImplicitDSA, B);
13624 if (NestedLoopCount == 0)
13634 {OMPC_grainsize, OMPC_num_tasks}))
13645 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13654 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13658 unsigned NestedLoopCount =
13662 if (NestedLoopCount == 0)
13666 "omp for loop exprs were not built");
13670 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13671 return DistributeDirective;
13689 VarsWithImplicitDSA, B);
13690 if (NestedLoopCount == 0)
13694 "omp for loop exprs were not built");
13697 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13708 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13716 VarsWithImplicitDSA, B);
13717 if (NestedLoopCount == 0)
13727 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13742 unsigned NestedLoopCount =
13746 if (NestedLoopCount == 0)
13756 NestedLoopCount, Clauses, AStmt, B);
13774 VarsWithImplicitDSA, B);
13775 if (NestedLoopCount == 0)
13785 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13799 unsigned NestedLoopCount =
13802 VarsWithImplicitDSA, B);
13803 if (NestedLoopCount == 0)
13813 NestedLoopCount, Clauses, AStmt, B);
13828 unsigned NestedLoopCount =
13832 if (NestedLoopCount == 0)
13836 "omp teams distribute loop exprs were not built");
13838 DSAStack->setParentTeamsRegionLoc(StartLoc);
13841 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13859 VarsWithImplicitDSA, B);
13860 if (NestedLoopCount == 0)
13869 DSAStack->setParentTeamsRegionLoc(StartLoc);
13872 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13882 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13890 VarsWithImplicitDSA, B);
13891 if (NestedLoopCount == 0)
13900 DSAStack->setParentTeamsRegionLoc(StartLoc);
13903 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13913 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13921 VarsWithImplicitDSA, B);
13923 if (NestedLoopCount == 0)
13927 "omp for loop exprs were not built");
13929 DSAStack->setParentTeamsRegionLoc(StartLoc);
13932 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13945 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
13947 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
13949 return C->getClauseKind() == OMPC_ompx_bare;
13952 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13957 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
13958 unsigned DiagNo = HasBareClause
13959 ? diag::err_ompx_more_than_three_expr_not_allowed
13960 : diag::err_omp_multi_expr_not_allowed;
13961 if (!checkNumExprsInClause<OMPNumTeamsClause>(*
this, Clauses,
13962 ClauseMaxNumExprs, DiagNo) ||
13963 !checkNumExprsInClause<OMPThreadLimitClause>(*
this, Clauses,
13964 ClauseMaxNumExprs, DiagNo))
13977 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13978 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13979 !checkNumExprsInClause<OMPThreadLimitClause>(
13980 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13992 VarsWithImplicitDSA, B);
13993 if (NestedLoopCount == 0)
13997 "omp target teams distribute loop exprs were not built");
14000 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14009 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14010 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14011 !checkNumExprsInClause<OMPThreadLimitClause>(
14012 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14016 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14024 VarsWithImplicitDSA, B);
14025 if (NestedLoopCount == 0)
14032 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14042 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14043 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14044 !checkNumExprsInClause<OMPThreadLimitClause>(
14045 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14049 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14054 unsigned NestedLoopCount =
14059 if (NestedLoopCount == 0)
14069 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14078 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14079 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14080 !checkNumExprsInClause<OMPThreadLimitClause>(
14081 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14085 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14093 VarsWithImplicitDSA, B);
14094 if (NestedLoopCount == 0)
14104 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14107bool SemaOpenMP::checkTransformableLoopNest(
14111 OriginalInits.emplace_back();
14114 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14116 VarsWithInheritedDSAType TmpDSA;
14117 unsigned SingleNumLoops =
14118 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14119 TmpDSA, LoopHelpers[Cnt]);
14120 if (SingleNumLoops == 0)
14122 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14123 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14124 OriginalInits.back().push_back(For->getInit());
14125 Body = For->getBody();
14127 assert(isa<CXXForRangeStmt>(CurStmt) &&
14128 "Expected canonical for or range-based for loops.");
14129 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14130 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14131 Body = CXXFor->getBody();
14133 OriginalInits.emplace_back();
14137 Stmt *DependentPreInits;
14138 if (
auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14139 DependentPreInits = Dir->getPreInits();
14140 else if (
auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14141 DependentPreInits = Dir->getPreInits();
14142 else if (
auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14143 DependentPreInits = Dir->getPreInits();
14144 else if (
auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14145 DependentPreInits = Dir->getPreInits();
14147 llvm_unreachable(
"Unhandled loop transformation");
14151 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14152 OriginalInits.pop_back();
14164 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14165 Stmt *RangeInit = CXXRangeFor->getInit();
14167 PreInits.push_back(RangeInit);
14169 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14174 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14180 llvm::append_range(PreInits, OriginalInit);
14183 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.
PreInits)) {
14184 PreInits.push_back(
new (Context)
DeclStmt(
14185 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14190 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14191 if (isa<OMPCapturedExprDecl>(CounterDecl))
14192 PreInits.push_back(
new (Context)
DeclStmt(
14200 size_t NumLoops = LoopStmts.size();
14202 AStmt,
false, NumLoops,
14203 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14204 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14205 LoopStmts[Cnt] = CurStmt;
14208 assert(!is_contained(LoopStmts,
nullptr) &&
14209 "Expecting a loop statement for each affected loop");
14219 const auto *SizesClause =
14220 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14221 if (!SizesClause ||
14222 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *
E) { return !E; }))
14224 unsigned NumLoops = SizesClause->getNumSizes();
14232 Stmt *Body =
nullptr;
14234 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14241 NumLoops, AStmt,
nullptr,
nullptr);
14243 assert(LoopHelpers.size() == NumLoops &&
14244 "Expecting loop iteration space dimensionality to match number of "
14246 assert(OriginalInits.size() == NumLoops &&
14247 "Expecting loop iteration space dimensionality to match number of "
14255 CaptureVars CopyTransformer(
SemaRef);
14260 FloorIndVars.resize(NumLoops);
14261 TileIndVars.resize(NumLoops);
14262 for (
unsigned I = 0; I < NumLoops; ++I) {
14265 assert(LoopHelper.
Counters.size() == 1 &&
14266 "Expect single-dimensional loop iteration space");
14267 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14268 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14274 std::string FloorCntName =
14275 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14278 FloorIndVars[I] = FloorCntDecl;
14283 std::string TileCntName =
14284 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14289 auto *TileCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
14290 TileCntDecl->setDeclName(
14292 TileIndVars[I] = TileCntDecl;
14300 Stmt *Inner = Body;
14302 auto MakeDimTileSize = [&
SemaRef = this->
SemaRef, &CopyTransformer, &Context,
14303 SizesClause, CurScope](
int I) ->
Expr * {
14304 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14305 if (isa<ConstantExpr>(DimTileSizeExpr))
14306 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14327 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14331 CurScope, {}, BO_LE,
14332 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14335 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14341 for (
int I = NumLoops - 1; I >= 0; --I) {
14344 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters[0]);
14346 Stmt *LoopStmt = LoopStmts[I];
14351 auto MakeTileIVRef = [&
SemaRef = this->
SemaRef, &TileIndVars, I, IVTy,
14354 OrigCntVar->getExprLoc());
14356 auto MakeFloorIVRef = [&
SemaRef = this->
SemaRef, &FloorIndVars, I, IVTy,
14359 OrigCntVar->getExprLoc());
14366 Decl *CounterDecl = TileIndVars[I];
14369 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14377 MakeFloorIVRef(), MakeDimTileSize(I));
14382 NumIterations, EndOfTile.
get());
14387 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
14388 if (!MinTileAndIterSpace.
isUsable())
14392 MakeTileIVRef(), MinTileAndIterSpace.
get());
14398 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeTileIVRef());
14419 BodyParts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14420 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14421 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14422 BodyParts.push_back(Inner);
14424 Inner->getBeginLoc(), Inner->getEndLoc());
14425 Inner =
new (Context)
14432 for (
int I = NumLoops - 1; I >= 0; --I) {
14433 auto &LoopHelper = LoopHelpers[I];
14434 Expr *NumIterations = LoopHelper.NumIterations;
14435 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14441 auto MakeFloorIVRef = [&
SemaRef = this->
SemaRef, &FloorIndVars, I, IVTy,
14452 Decl *CounterDecl = FloorIndVars[I];
14462 MakeFloorIVRef(), NumIterations);
14469 MakeFloorIVRef(), MakeDimTileSize(I));
14473 Inner =
new (Context)
14475 IncrStmt.
get(), Inner, LoopHelper.Init->getBeginLoc(),
14476 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14495 {OMPC_partial, OMPC_full}))
14499 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14501 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14502 assert(!(FullClause && PartialClause) &&
14503 "mutual exclusivity must have been checked before");
14505 constexpr unsigned NumLoops = 1;
14506 Stmt *Body =
nullptr;
14510 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14511 Body, OriginalInits))
14514 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14519 NumGeneratedLoops,
nullptr,
nullptr);
14521 assert(LoopHelpers.size() == NumLoops &&
14522 "Expecting a single-dimensional loop iteration space");
14523 assert(OriginalInits.size() == NumLoops &&
14524 "Expecting a single-dimensional loop iteration space");
14532 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14534 <<
"#pragma omp unroll full";
14542 if (NumGeneratedLoops == 0)
14544 NumGeneratedLoops,
nullptr,
nullptr);
14589 Stmt *LoopStmt =
nullptr;
14594 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14596 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14597 QualType IVTy = IterationVarRef->getType();
14598 assert(LoopHelper.
Counters.size() == 1 &&
14599 "Expecting a single-dimensional loop iteration space");
14600 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14606 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14607 FactorLoc = FactorVal->getExprLoc();
14612 assert(Factor > 0 &&
"Expected positive unroll factor");
14613 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
14625 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14626 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
14627 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
14628 std::string InnerTripCountName =
14629 (Twine(
".unroll_inner.tripcount.") + OrigVarName).str();
14634 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
14640 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14642 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
14648 CaptureVars CopyTransformer(
SemaRef);
14649 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
14672 MakeOuterRef(), MakeFactorExpr());
14677 MakeInnerRef(), EndOfTile.
get());
14682 MakeInnerRef(), MakeNumIterations());
14687 InnerCond1.
get(), InnerCond2.
get());
14693 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeInnerRef());
14699 InnerBodyStmts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14700 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14701 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14702 InnerBodyStmts.push_back(Body);
14706 ForStmt *InnerFor =
new (Context)
14707 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
14723 LoopHintAttr *UnrollHintAttr =
14724 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14725 LoopHintAttr::Numeric, MakeFactorExpr());
14742 MakeOuterRef(), MakeNumIterations());
14749 MakeOuterRef(), MakeFactorExpr());
14754 ForStmt *OuterFor =
new (Context)
14755 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
14760 NumGeneratedLoops, OuterFor,
14774 constexpr unsigned NumLoops = 1;
14775 Stmt *Body =
nullptr;
14779 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14780 Body, OriginalInits))
14789 assert(LoopHelpers.size() == NumLoops &&
14790 "Expecting a single-dimensional loop iteration space");
14791 assert(OriginalInits.size() == NumLoops &&
14792 "Expecting a single-dimensional loop iteration space");
14796 Stmt *LoopStmt =
nullptr;
14801 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14803 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14804 QualType IVTy = IterationVarRef->getType();
14806 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14819 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14821 ForwardIVName += OrigVarName;
14823 ReversedIVName += OrigVarName;
14856 CaptureVars CopyTransformer(
SemaRef);
14857 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
14865 auto MakeForwardRef = [&
SemaRef = this->
SemaRef, ForwardIVDecl, IVTy,
14872 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14873 ReversedIVDecl->setDeclName(
14881 ForwardIVDecl->
getType(), OrigVarLoc);
14885 if (!
Init.isUsable())
14894 MakeForwardRef(), MakeNumIterations());
14903 UO_PreInc, MakeForwardRef());
14914 MakeNumIterations(), One);
14922 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14930 BodyStmts.reserve(LoopHelper.
Updates.size() + 2 +
14931 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14932 BodyStmts.push_back(InitReversed.
get());
14933 llvm::append_range(BodyStmts, LoopHelper.
Updates);
14934 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14935 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14936 BodyStmts.push_back(Body);
14937 auto *ReversedBody =
14942 auto *ReversedFor =
new (Context)
14963 constexpr size_t NumLoops = 2;
14967 Stmt *Body =
nullptr;
14969 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14970 LoopHelpers, Body, OriginalInits))
14976 NumLoops, AStmt,
nullptr,
nullptr);
14978 assert(LoopHelpers.size() == NumLoops &&
14979 "Expecting loop iteration space dimensionaly to match number of "
14981 assert(OriginalInits.size() == NumLoops &&
14982 "Expecting loop iteration space dimensionaly to match number of "
14986 constexpr uint64_t Permutation[] = {1, 0};
14994 for (
auto I : llvm::seq<int>(NumLoops)) {
14997 assert(LoopHelper.
Counters.size() == 1 &&
14998 "Single-dimensional loop iteration space expected");
14999 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
15001 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15007 CaptureVars CopyTransformer(
SemaRef);
15012 Stmt *Inner = Body;
15013 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15015 uint64_t SourceIdx = Permutation[TargetIdx];
15017 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15018 assert(SourceHelper.
Counters.size() == 1 &&
15019 "Single-dimensional loop iteration space expected");
15020 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.
Counters.front());
15026 "Expected the logical iteration counter to be an integer");
15028 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15033 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
15035 CopyTransformer.TransformExpr(SourceHelper.
NumIterations));
15042 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
15043 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
15044 PermutedCntDecl->setDeclName(
15046 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15047 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15056 if (!Zero.isUsable())
15062 OrigCntVar->getEndLoc());
15072 MakePermutedRef(), MakeNumIterations());
15081 CurScope, SourceHelper.
Inc->
getExprLoc(), UO_PreInc, MakePermutedRef());
15087 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15088 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15089 BodyParts.push_back(Inner);
15091 Inner->getBeginLoc(), Inner->getEndLoc());
15092 Inner =
new (Context)
ForStmt(
15093 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
15099 NumLoops, AStmt, Inner,
15113 case OMPC_num_threads:
15122 case OMPC_allocator:
15125 case OMPC_collapse:
15131 case OMPC_priority:
15143 case OMPC_novariants:
15146 case OMPC_nocontext:
15161 case OMPC_ompx_dyn_cgroup_mem:
15167 case OMPC_grainsize:
15168 case OMPC_num_tasks:
15172 case OMPC_proc_bind:
15173 case OMPC_schedule:
15175 case OMPC_firstprivate:
15176 case OMPC_lastprivate:
15178 case OMPC_reduction:
15179 case OMPC_task_reduction:
15180 case OMPC_in_reduction:
15184 case OMPC_copyprivate:
15187 case OMPC_mergeable:
15188 case OMPC_threadprivate:
15190 case OMPC_allocate:
15207 case OMPC_dist_schedule:
15208 case OMPC_defaultmap:
15213 case OMPC_use_device_ptr:
15214 case OMPC_use_device_addr:
15215 case OMPC_is_device_ptr:
15216 case OMPC_unified_address:
15217 case OMPC_unified_shared_memory:
15218 case OMPC_reverse_offload:
15219 case OMPC_dynamic_allocators:
15220 case OMPC_atomic_default_mem_order:
15221 case OMPC_device_type:
15223 case OMPC_nontemporal:
15226 case OMPC_severity:
15228 case OMPC_inclusive:
15229 case OMPC_exclusive:
15230 case OMPC_uses_allocators:
15231 case OMPC_affinity:
15234 case OMPC_num_teams:
15235 case OMPC_thread_limit:
15237 llvm_unreachable(
"Clause is not allowed.");
15250 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15251 "Invalid directive with CKind-clause");
15254 if (NameModifier != OMPD_unknown &&
15255 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15256 return OMPD_unknown;
15275 case OMPD_teams_loop:
15276 case OMPD_target_teams_loop:
15280 case OMPD_target_update:
15281 case OMPD_target_enter_data:
15282 case OMPD_target_exit_data:
15288 case OMPC_num_teams:
15289 case OMPC_thread_limit:
15290 case OMPC_ompx_dyn_cgroup_mem:
15291 if (Leafs[0] == OMPD_target)
15292 return OMPD_target;
15295 if (Leafs[0] == OMPD_target ||
15296 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15297 OMPD_target_enter_data, OMPD_target_exit_data},
15301 case OMPC_novariants:
15302 case OMPC_nocontext:
15303 if (DKind == OMPD_dispatch)
15307 if (DKind == OMPD_metadirective)
15308 return OMPD_metadirective;
15311 return OMPD_unknown;
15324 int InnermostIdx = [&]() {
15325 for (
int I = EndIdx - 1; I >= 0; --I) {
15326 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15334 for (
int I = InnermostIdx - 1; I >= 0; --I) {
15339 if (Regions[0] != OMPD_unknown)
15340 return Regions.back();
15342 return OMPD_unknown;
15347 for (
int I = 0,
E = Leafs.size(); I !=
E; ++I) {
15348 if (Leafs[I] == Dir)
15354 int End = NameModifier == OMPD_unknown ? Leafs.size()
15355 : GetLeafIndex(NameModifier);
15356 return GetEnclosingRegion(End, CKind);
15359 return OMPD_unknown;
15367 Stmt *HelperValStmt =
nullptr;
15370 !
Condition->isInstantiationDependent() &&
15371 !
Condition->containsUnexpandedParameterPack()) {
15376 ValExpr = Val.
get();
15380 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
15381 if (CaptureRegion != OMPD_unknown &&
15384 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15385 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15391 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15392 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15400 Stmt *HelperValStmt =
nullptr;
15403 !
Condition->isInstantiationDependent() &&
15404 !
Condition->containsUnexpandedParameterPack()) {
15414 if (CaptureRegion != OMPD_unknown &&
15417 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15418 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15424 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15435 IntConvertDiagnoser()
15436 : ICEConvertDiagnoser(
false,
false,
true) {}
15439 return S.
Diag(
Loc, diag::err_omp_not_integral) <<
T;
15443 return S.
Diag(
Loc, diag::err_omp_incomplete_type) <<
T;
15448 return S.
Diag(
Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
15457 return S.
Diag(
Loc, diag::err_omp_ambiguous_conversion) <<
T;
15466 llvm_unreachable(
"conversion functions are permitted");
15468 } ConvertDiagnoser;
15474 bool StrictlyPositive,
bool BuildCapture =
false,
15477 Stmt **HelperValStmt =
nullptr) {
15483 if (
Value.isInvalid())
15486 ValExpr =
Value.get();
15488 if (std::optional<llvm::APSInt>
Result =
15490 if (
Result->isSigned() &&
15491 !((!StrictlyPositive &&
Result->isNonNegative()) ||
15492 (StrictlyPositive &&
Result->isStrictlyPositive()))) {
15493 SemaRef.
Diag(
Loc, diag::err_omp_negative_expression_in_clause)
15494 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15503 if (*CaptureRegion != OMPD_unknown &&
15506 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15507 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15518 Expr *ValExpr = NumThreads;
15519 Stmt *HelperValStmt =
nullptr;
15530 if (CaptureRegion != OMPD_unknown &&
15533 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15534 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15539 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15544 bool SuppressExprDiags) {
15553 if (SuppressExprDiags) {
15557 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
15560 llvm_unreachable(
"Diagnostic suppressed");
15572 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
15573 (!StrictlyPositive && !
Result.isNonNegative())) {
15575 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15579 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !
Result.isPowerOf2()) {
15584 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
15586 else if (CKind == OMPC_ordered)
15621 DSAStackTy *Stack) {
15622 if (!Stack->getOMPAllocatorHandleT().isNull())
15629 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15630 <<
"omp_allocator_handle_t";
15635 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15638 bool ErrorFound =
false;
15639 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15640 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
15641 StringRef Allocator =
15642 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15644 auto *VD = dyn_cast_or_null<ValueDecl>(
15664 Stack->setAllocator(AllocatorKind, Res.
get());
15667 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15668 <<
"omp_allocator_handle_t";
15685 if (Allocator.isInvalid())
15688 Allocator.get(),
DSAStack->getOMPAllocatorHandleT(),
15691 if (Allocator.isInvalid())
15717 Expr *NumForLoops) {
15723 if (NumForLoops && LParenLoc.
isValid()) {
15728 NumForLoops = NumForLoopsResult.
get();
15730 NumForLoops =
nullptr;
15734 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
15735 StartLoc, LParenLoc, EndLoc);
15736 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
15747 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15749 case OMPC_proc_bind:
15751 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15753 case OMPC_atomic_default_mem_order:
15756 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15760 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15764 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15768 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15772 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15774 case OMPC_severity:
15777 LParenLoc, EndLoc);
15781 case OMPC_num_threads:
15785 case OMPC_allocator:
15786 case OMPC_collapse:
15787 case OMPC_schedule:
15789 case OMPC_firstprivate:
15790 case OMPC_lastprivate:
15792 case OMPC_reduction:
15793 case OMPC_task_reduction:
15794 case OMPC_in_reduction:
15798 case OMPC_copyprivate:
15802 case OMPC_mergeable:
15803 case OMPC_threadprivate:
15804 case OMPC_allocate:
15821 case OMPC_num_teams:
15822 case OMPC_thread_limit:
15823 case OMPC_priority:
15824 case OMPC_grainsize:
15826 case OMPC_num_tasks:
15828 case OMPC_dist_schedule:
15829 case OMPC_defaultmap:
15834 case OMPC_use_device_ptr:
15835 case OMPC_use_device_addr:
15836 case OMPC_is_device_ptr:
15837 case OMPC_has_device_addr:
15838 case OMPC_unified_address:
15839 case OMPC_unified_shared_memory:
15840 case OMPC_reverse_offload:
15841 case OMPC_dynamic_allocators:
15842 case OMPC_device_type:
15844 case OMPC_nontemporal:
15846 case OMPC_novariants:
15847 case OMPC_nocontext:
15849 case OMPC_inclusive:
15850 case OMPC_exclusive:
15851 case OMPC_uses_allocators:
15852 case OMPC_affinity:
15856 llvm_unreachable(
"Clause is not allowed.");
15865 llvm::raw_svector_ostream Out(Buffer);
15866 unsigned Skipped = Exclude.size();
15867 for (
unsigned I =
First; I <
Last; ++I) {
15868 if (llvm::is_contained(Exclude, I)) {
15873 if (I + Skipped + 2 ==
Last)
15875 else if (I + Skipped + 1 !=
Last)
15878 return std::string(Out.str());
15886 if (Kind == OMP_DEFAULT_unknown) {
15887 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15889 unsigned(OMP_DEFAULT_unknown))
15890 << getOpenMPClauseName(OMPC_default);
15895 case OMP_DEFAULT_none:
15896 DSAStack->setDefaultDSANone(KindKwLoc);
15898 case OMP_DEFAULT_shared:
15899 DSAStack->setDefaultDSAShared(KindKwLoc);
15901 case OMP_DEFAULT_firstprivate:
15902 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15904 case OMP_DEFAULT_private:
15905 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15908 llvm_unreachable(
"DSA unexpected in OpenMP default clause");
15920 if (Kind == OMP_PROC_BIND_unknown) {
15921 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15923 unsigned(OMP_PROC_BIND_master),
15926 ? OMP_PROC_BIND_primary
15927 : OMP_PROC_BIND_spread) +
15929 << getOpenMPClauseName(OMPC_proc_bind);
15932 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
15933 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15935 unsigned(OMP_PROC_BIND_master),
15937 unsigned(OMP_PROC_BIND_spread) + 1)
15938 << getOpenMPClauseName(OMPC_proc_bind);
15947 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15949 OMPC_atomic_default_mem_order, 0,
15951 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15955 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15964 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15967 << getOpenMPClauseName(OMPC_at);
15971 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15980 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15983 << getOpenMPClauseName(OMPC_severity);
15994 assert(ME &&
"NULL expr in Message clause");
15995 if (!isa<StringLiteral>(ME)) {
15997 << getOpenMPClauseName(OMPC_message);
16008 if (Kind != OMPC_ORDER_concurrent ||
16013 "OMPC_ORDER_unknown not greater than 0");
16015 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16019 << getOpenMPClauseName(OMPC_order);
16024 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16028 << getOpenMPClauseName(OMPC_order);
16030 DSAStack->setRegionHasOrderConcurrent(
true);
16033 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
16034 DSAStack->getCurScope()->setFlags(existingFlags |
16040 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16049 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16051 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16052 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16054 Except.push_back(OMPC_DEPEND_inoutset);
16055 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16058 << getOpenMPClauseName(OMPC_update);
16062 KindKwLoc, Kind, EndLoc);
16071 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
16081 QualType SizeTy = SizeExpr->getType();
16110 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16111 SizeExpr =
nullptr;
16115 SanitizedSizeExprs);
16131 FactorExpr, OMPC_partial,
true);
16134 FactorExpr = FactorResult.
get();
16149 LParenLoc, EndLoc);
16159 case OMPC_schedule:
16160 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16161 assert(Argument.size() == NumberOfElements &&
16162 ArgumentLoc.size() == NumberOfElements);
16167 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16168 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16171 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16173 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16176 case OMPC_dist_schedule:
16179 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16181 case OMPC_defaultmap:
16182 enum { Modifier, DefaultmapKind };
16186 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16190 enum { OrderModifier, OrderKind };
16194 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16197 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16200 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16202 case OMPC_grainsize:
16203 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16204 "Modifier for grainsize clause and its location are expected.");
16207 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16209 case OMPC_num_tasks:
16210 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16211 "Modifier for num_tasks clause and its location are expected.");
16214 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16217 case OMPC_num_threads:
16221 case OMPC_allocator:
16222 case OMPC_collapse:
16224 case OMPC_proc_bind:
16226 case OMPC_firstprivate:
16227 case OMPC_lastprivate:
16229 case OMPC_reduction:
16230 case OMPC_task_reduction:
16231 case OMPC_in_reduction:
16235 case OMPC_copyprivate:
16239 case OMPC_mergeable:
16240 case OMPC_threadprivate:
16241 case OMPC_allocate:
16258 case OMPC_num_teams:
16259 case OMPC_thread_limit:
16260 case OMPC_priority:
16267 case OMPC_use_device_ptr:
16268 case OMPC_use_device_addr:
16269 case OMPC_is_device_ptr:
16270 case OMPC_has_device_addr:
16271 case OMPC_unified_address:
16272 case OMPC_unified_shared_memory:
16273 case OMPC_reverse_offload:
16274 case OMPC_dynamic_allocators:
16275 case OMPC_atomic_default_mem_order:
16276 case OMPC_device_type:
16278 case OMPC_nontemporal:
16280 case OMPC_severity:
16283 case OMPC_novariants:
16284 case OMPC_nocontext:
16286 case OMPC_inclusive:
16287 case OMPC_exclusive:
16288 case OMPC_uses_allocators:
16289 case OMPC_affinity:
16293 llvm_unreachable(
"Clause is not allowed.");
16304 Excluded.push_back(M2);
16305 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16306 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16307 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16308 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16309 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16314 << getOpenMPClauseName(OMPC_schedule);
16332 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16333 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16334 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16335 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16336 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16342 std::string Values;
16352 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16353 << Values << getOpenMPClauseName(OMPC_schedule);
16361 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16362 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16363 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16364 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16365 diag::err_omp_schedule_nonmonotonic_static);
16368 Expr *ValExpr = ChunkSize;
16369 Stmt *HelperValStmt =
nullptr;
16380 ValExpr = Val.
get();
16385 if (std::optional<llvm::APSInt>
Result =
16387 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
16388 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16393 DSAStack->getCurrentDirective(), OMPC_schedule,
16397 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16398 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16406 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16423 case OMPC_mergeable:
16471 case OMPC_unified_address:
16474 case OMPC_unified_shared_memory:
16477 case OMPC_reverse_offload:
16480 case OMPC_dynamic_allocators:
16494 case OMPC_ompx_bare:
16499 case OMPC_num_threads:
16503 case OMPC_allocator:
16504 case OMPC_collapse:
16505 case OMPC_schedule:
16507 case OMPC_firstprivate:
16508 case OMPC_lastprivate:
16510 case OMPC_reduction:
16511 case OMPC_task_reduction:
16512 case OMPC_in_reduction:
16516 case OMPC_copyprivate:
16518 case OMPC_proc_bind:
16519 case OMPC_threadprivate:
16520 case OMPC_allocate:
16526 case OMPC_num_teams:
16527 case OMPC_thread_limit:
16528 case OMPC_priority:
16529 case OMPC_grainsize:
16530 case OMPC_num_tasks:
16532 case OMPC_dist_schedule:
16533 case OMPC_defaultmap:
16538 case OMPC_use_device_ptr:
16539 case OMPC_use_device_addr:
16540 case OMPC_is_device_ptr:
16541 case OMPC_has_device_addr:
16542 case OMPC_atomic_default_mem_order:
16543 case OMPC_device_type:
16545 case OMPC_nontemporal:
16548 case OMPC_severity:
16550 case OMPC_novariants:
16551 case OMPC_nocontext:
16553 case OMPC_inclusive:
16554 case OMPC_exclusive:
16555 case OMPC_uses_allocators:
16556 case OMPC_affinity:
16558 case OMPC_ompx_dyn_cgroup_mem:
16560 llvm_unreachable(
"Clause is not allowed.");
16619 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16700 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16701 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
16702 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16703 <<
Expected << getOpenMPDirectiveName(OMPD_interop);
16716 bool HasInitClause =
false;
16717 bool IsTargetSync =
false;
16721 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
16722 HasInitClause =
true;
16723 if (InitClause->getIsTargetSync())
16724 IsTargetSync =
true;
16725 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
16729 if (DependClause && HasInitClause && !IsTargetSync) {
16730 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16744 if (ClauseKind == OMPC_init) {
16745 auto *
E = cast<OMPInitClause>(
C)->getInteropVar();
16747 }
else if (ClauseKind == OMPC_use) {
16748 auto *
E = cast<OMPUseClause>(
C)->getInteropVar();
16750 }
else if (ClauseKind == OMPC_destroy) {
16751 auto *
E = cast<OMPDestroyClause>(
C)->getInteropVar();
16756 if (!InteropVars.insert(
DeclResult.first).second) {
16757 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16773 Expr *RefExpr = InteropVarExpr;
16776 false,
"omp_interop_t");
16787 bool HasError =
false;
16793 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
16794 InteropType =
QualType(TD->getTypeForDecl(), 0);
16803 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
16804 <<
"omp_interop_t";
16810 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16816 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16818 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
16840 if (isa<StringLiteral>(
E))
16847 StartLoc, LParenLoc, VarLoc, EndLoc);
16860 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16869 DSAStack->getCurrentDirective() == OMPD_depobj) {
16870 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16871 << getOpenMPClauseName(OMPC_destroy)
16872 << getOpenMPDirectiveName(OMPD_depobj);
16888 Stmt *HelperValStmt =
nullptr;
16891 !
Condition->isInstantiationDependent() &&
16892 !
Condition->containsUnexpandedParameterPack()) {
16902 if (CaptureRegion != OMPD_unknown &&
16905 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16906 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16912 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16920 Stmt *HelperValStmt =
nullptr;
16923 !
Condition->isInstantiationDependent() &&
16924 !
Condition->containsUnexpandedParameterPack()) {
16934 if (CaptureRegion != OMPD_unknown &&
16937 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16938 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16944 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16951 Expr *ValExpr = ThreadID;
16952 Stmt *HelperValStmt =
nullptr;
16957 if (CaptureRegion != OMPD_unknown &&
16960 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16961 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16966 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16977 int ExtraModifier =
Data.ExtraModifier;
16984 case OMPC_firstprivate:
16987 case OMPC_lastprivate:
16989 "Unexpected lastprivate modifier.");
16992 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
16997 case OMPC_reduction:
16999 "Unexpected lastprivate modifier.");
17002 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17003 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17005 case OMPC_task_reduction:
17007 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17008 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17010 case OMPC_in_reduction:
17012 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17013 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17017 "Unexpected linear modifier.");
17019 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
17021 ColonLoc,
Data.StepModifierLoc, EndLoc);
17025 LParenLoc, ColonLoc, EndLoc);
17030 case OMPC_copyprivate:
17038 "Unexpected depend modifier.");
17041 ColonLoc,
Data.OmpAllMemoryLoc},
17042 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17046 "Unexpected map modifier.");
17048 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
17049 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
17051 ExtraModifierLoc, ColonLoc, VarList, Locs);
17056 Data.ReductionOrMapperIdScopeSpec,
17057 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17061 Data.ReductionOrMapperIdScopeSpec,
17062 Data.ReductionOrMapperId, ColonLoc, VarList,
17065 case OMPC_use_device_ptr:
17068 case OMPC_use_device_addr:
17071 case OMPC_is_device_ptr:
17074 case OMPC_has_device_addr:
17077 case OMPC_allocate:
17079 LParenLoc, ColonLoc, EndLoc);
17081 case OMPC_nontemporal:
17084 case OMPC_inclusive:
17087 case OMPC_exclusive:
17090 case OMPC_affinity:
17092 Data.DepModOrTailExpr, VarList);
17094 case OMPC_doacross:
17097 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17099 case OMPC_num_teams:
17102 case OMPC_thread_limit:
17108 case OMPC_num_threads:
17112 case OMPC_allocator:
17113 case OMPC_collapse:
17115 case OMPC_proc_bind:
17116 case OMPC_schedule:
17120 case OMPC_mergeable:
17121 case OMPC_threadprivate:
17135 case OMPC_priority:
17136 case OMPC_grainsize:
17138 case OMPC_num_tasks:
17140 case OMPC_dist_schedule:
17141 case OMPC_defaultmap:
17144 case OMPC_unified_address:
17145 case OMPC_unified_shared_memory:
17146 case OMPC_reverse_offload:
17147 case OMPC_dynamic_allocators:
17148 case OMPC_atomic_default_mem_order:
17149 case OMPC_device_type:
17153 case OMPC_severity:
17156 case OMPC_novariants:
17157 case OMPC_nocontext:
17159 case OMPC_uses_allocators:
17163 llvm_unreachable(
"Clause is not allowed.");
17194 bool IsImplicitClause =
17196 for (
Expr *RefExpr : VarList) {
17197 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
17200 Expr *SimpleRefExpr = RefExpr;
17204 Vars.push_back(RefExpr);
17205 PrivateCopies.push_back(
nullptr);
17212 auto *VD = dyn_cast<VarDecl>(
D);
17218 diag::err_omp_private_incomplete_type))
17220 Type =
Type.getNonReferenceType();
17240 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17241 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17242 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17243 << getOpenMPClauseName(OMPC_private);
17252 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17253 << getOpenMPClauseName(OMPC_private) <<
Type
17254 << getOpenMPDirectiveName(CurrDir);
17255 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17258 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17273 CurrDir == OMPD_target) {
17275 if (
DSAStack->checkMappableExprComponentListsForDecl(
17279 ConflictKind = WhereFoundClauseKind;
17282 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17283 << getOpenMPClauseName(OMPC_private)
17284 << getOpenMPClauseName(ConflictKind)
17285 << getOpenMPDirectiveName(CurrDir);
17304 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17313 auto *FD = dyn_cast<FieldDecl>(
D);
17317 RefExpr->getExprLoc());
17321 if (!IsImplicitClause)
17322 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17324 ? RefExpr->IgnoreParens()
17326 PrivateCopies.push_back(VDPrivateRefExpr);
17333 Vars, PrivateCopies);
17344 bool IsImplicitClause =
17348 for (
Expr *RefExpr : VarList) {
17349 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
17352 Expr *SimpleRefExpr = RefExpr;
17356 Vars.push_back(RefExpr);
17357 PrivateCopies.push_back(
nullptr);
17358 Inits.push_back(
nullptr);
17364 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17366 auto *VD = dyn_cast<VarDecl>(
D);
17372 diag::err_omp_firstprivate_incomplete_type))
17374 Type =
Type.getNonReferenceType();
17384 DSAStackTy::DSAVarData TopDVar;
17385 if (!IsImplicitClause) {
17386 DSAStackTy::DSAVarData DVar =
17398 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17400 DVar.CKind != OMPC_lastprivate) &&
17402 Diag(ELoc, diag::err_omp_wrong_dsa)
17403 << getOpenMPClauseName(DVar.CKind)
17404 << getOpenMPClauseName(OMPC_firstprivate);
17420 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17421 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17422 Diag(ELoc, diag::err_omp_wrong_dsa)
17423 << getOpenMPClauseName(DVar.CKind)
17424 << getOpenMPClauseName(OMPC_firstprivate);
17448 DVar =
DSAStack->getImplicitDSA(
D,
true);
17449 if (DVar.CKind != OMPC_shared &&
17452 DVar.DKind == OMPD_unknown)) {
17453 Diag(ELoc, diag::err_omp_required_access)
17454 << getOpenMPClauseName(OMPC_firstprivate)
17455 << getOpenMPClauseName(OMPC_shared);
17475 return C == OMPC_reduction && !AppliedToPointee;
17483 if (DVar.CKind == OMPC_reduction &&
17487 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17488 << getOpenMPDirectiveName(DVar.DKind);
17504 CurrDir == OMPD_target) {
17506 if (
DSAStack->checkMappableExprComponentListsForDecl(
17511 ConflictKind = WhereFoundClauseKind;
17514 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17515 << getOpenMPClauseName(OMPC_firstprivate)
17516 << getOpenMPClauseName(ConflictKind)
17517 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17527 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17528 << getOpenMPClauseName(OMPC_firstprivate) <<
Type
17529 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17530 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17533 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17542 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17548 Expr *VDInitRefExpr =
nullptr;
17558 ElemType,
".firstprivate.temp");
17573 ".firstprivate.temp");
17575 RefExpr->getExprLoc());
17581 if (IsImplicitClause) {
17582 Diag(RefExpr->getExprLoc(),
17583 diag::note_omp_task_predetermined_firstprivate_here);
17590 RefExpr->getExprLoc());
17593 if (TopDVar.CKind == OMPC_lastprivate) {
17594 Ref = TopDVar.PrivateCopy;
17596 auto *FD = dyn_cast<FieldDecl>(
D);
17601 RefExpr->getExprLoc());
17605 ExprCaptures.push_back(Ref->
getDecl());
17608 if (!IsImplicitClause)
17609 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17611 ? RefExpr->IgnoreParens()
17613 PrivateCopies.push_back(VDPrivateRefExpr);
17614 Inits.push_back(VDInitRefExpr);
17621 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17630 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
17631 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17634 << getOpenMPClauseName(OMPC_lastprivate);
17644 for (
Expr *RefExpr : VarList) {
17645 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17648 Expr *SimpleRefExpr = RefExpr;
17652 Vars.push_back(RefExpr);
17653 SrcExprs.push_back(
nullptr);
17654 DstExprs.push_back(
nullptr);
17655 AssignmentOps.push_back(
nullptr);
17662 auto *VD = dyn_cast<VarDecl>(
D);
17668 diag::err_omp_lastprivate_incomplete_type))
17670 Type =
Type.getNonReferenceType();
17687 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17688 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17691 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17705 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17706 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17708 DVar.CKind != OMPC_firstprivate) &&
17709 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
17710 Diag(ELoc, diag::err_omp_wrong_dsa)
17711 << getOpenMPClauseName(DVar.CKind)
17712 << getOpenMPClauseName(OMPC_lastprivate);
17723 DSAStackTy::DSAVarData TopDVar = DVar;
17727 DVar =
DSAStack->getImplicitDSA(
D,
true);
17728 if (DVar.CKind != OMPC_shared) {
17729 Diag(ELoc, diag::err_omp_required_access)
17730 << getOpenMPClauseName(OMPC_lastprivate)
17731 << getOpenMPClauseName(OMPC_shared);
17747 Type.getUnqualifiedType(),
".lastprivate.src",
17758 PseudoDstExpr, PseudoSrcExpr);
17768 if (TopDVar.CKind == OMPC_firstprivate) {
17769 Ref = TopDVar.PrivateCopy;
17773 ExprCaptures.push_back(Ref->
getDecl());
17775 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17783 SimpleRefExpr, RefRes.
get());
17786 ExprPostUpdates.push_back(
17790 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17792 ? RefExpr->IgnoreParens()
17794 SrcExprs.push_back(PseudoSrcExpr);
17795 DstExprs.push_back(PseudoDstExpr);
17796 AssignmentOps.push_back(AssignmentOp.
get());
17803 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17804 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17814 for (
Expr *RefExpr : VarList) {
17815 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17818 Expr *SimpleRefExpr = RefExpr;
17822 Vars.push_back(RefExpr);
17828 auto *VD = dyn_cast<VarDecl>(
D);
17836 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17837 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17839 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17840 << getOpenMPClauseName(OMPC_shared);
17849 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17851 ? RefExpr->IgnoreParens()
17863class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
17868 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
17869 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
17870 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17872 if (DVar.CKind != OMPC_unknown)
17874 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17881 return DVarPrivate.CKind != OMPC_unknown;
17885 bool VisitStmt(
Stmt *S) {
17886 for (
Stmt *Child : S->children()) {
17887 if (Child && Visit(Child))
17892 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17899class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
17906 : BaseTransform(SemaRef),
Field(
FieldDecl), CapturedExpr(nullptr) {}
17910 E->getMemberDecl() == Field) {
17912 return CapturedExpr;
17914 return BaseTransform::TransformMemberExpr(
E);
17916 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
17920template <
typename T,
typename U>
17923 for (
U &
Set : Lookups) {
17924 for (
auto *
D :
Set) {
17925 if (
T Res = Gen(cast<ValueDecl>(
D)))
17940 auto ND = cast<NamedDecl>(RD);
17958 AssociatedClasses);
17971 for (
auto *NS : AssociatedNamespaces) {
17984 for (
auto *
D : R) {
17985 auto *Underlying =
D;
17986 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
17987 Underlying = USD->getTargetDecl();
17989 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
17990 !isa<OMPDeclareMapperDecl>(Underlying))
17997 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
17998 Underlying = USD->getTargetDecl();
18000 Lookups.emplace_back();
18001 Lookups.back().addDecl(Underlying);
18021 S = S->getParent();
18022 }
while (S && !S->isDeclScope(
D));
18024 S = S->getParent();
18025 Lookups.emplace_back();
18026 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18029 }
else if (
auto *ULE =
18030 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18032 Decl *PrevD =
nullptr;
18036 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(
D))
18037 Lookups.back().addDecl(DRD);
18044 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
18045 return !D->isInvalidDecl() &&
18046 (D->getType()->isDependentType() ||
18047 D->getType()->isInstantiationDependentType() ||
18048 D->getType()->containsUnexpandedParameterPack());
18061 true, ResSet.
begin(), ResSet.
end(),
false,
18083 TyRec->getDecl()->getDefinition()) {
18086 if (Lookup.
empty()) {
18087 Lookups.emplace_back();
18088 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18095 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18105 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18129 if (ReductionIdScopeSpec.
isSet()) {
18130 SemaRef.
Diag(
Loc, diag::err_omp_not_resolved_reduction_identifier)
18139struct ReductionData {
18164 unsigned RedModifier = 0;
18165 ReductionData() =
delete;
18167 ReductionData(
unsigned Size,
unsigned Modifier = 0) : RedModifier(Modifier) {
18168 Vars.reserve(Size);
18169 Privates.reserve(Size);
18170 LHSs.reserve(Size);
18171 RHSs.reserve(Size);
18172 ReductionOps.reserve(Size);
18173 if (RedModifier == OMPC_REDUCTION_inscan) {
18174 InscanCopyOps.reserve(Size);
18175 InscanCopyArrayTemps.reserve(Size);
18176 InscanCopyArrayElems.reserve(Size);
18178 TaskgroupDescriptors.reserve(Size);
18179 ExprCaptures.reserve(Size);
18180 ExprPostUpdates.reserve(Size);
18184 void push(
Expr *Item,
Expr *ReductionOp) {
18185 Vars.emplace_back(Item);
18186 Privates.emplace_back(
nullptr);
18187 LHSs.emplace_back(
nullptr);
18188 RHSs.emplace_back(
nullptr);
18189 ReductionOps.emplace_back(ReductionOp);
18190 TaskgroupDescriptors.emplace_back(
nullptr);
18191 if (RedModifier == OMPC_REDUCTION_inscan) {
18192 InscanCopyOps.push_back(
nullptr);
18193 InscanCopyArrayTemps.push_back(
nullptr);
18194 InscanCopyArrayElems.push_back(
nullptr);
18199 Expr *TaskgroupDescriptor,
Expr *CopyOp,
Expr *CopyArrayTemp,
18200 Expr *CopyArrayElem) {
18201 Vars.emplace_back(Item);
18202 Privates.emplace_back(Private);
18203 LHSs.emplace_back(LHS);
18204 RHSs.emplace_back(RHS);
18205 ReductionOps.emplace_back(ReductionOp);
18206 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18207 if (RedModifier == OMPC_REDUCTION_inscan) {
18208 InscanCopyOps.push_back(CopyOp);
18209 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18210 InscanCopyArrayElems.push_back(CopyArrayElem);
18212 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
18213 CopyArrayElem ==
nullptr &&
18214 "Copy operation must be used for inscan reductions only.");
18224 if (Length ==
nullptr) {
18231 SingleElement =
true;
18232 ArraySizes.push_back(llvm::APSInt::get(1));
18235 if (!Length->EvaluateAsInt(
Result, Context))
18238 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18239 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18240 ArraySizes.push_back(ConstantLengthValue);
18248 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
18249 Length = TempOASE->getLength();
18250 if (Length ==
nullptr) {
18257 ArraySizes.push_back(llvm::APSInt::get(1));
18260 if (!Length->EvaluateAsInt(
Result, Context))
18263 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18264 if (ConstantLengthValue.getSExtValue() != 1)
18267 ArraySizes.push_back(ConstantLengthValue);
18269 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18273 if (!SingleElement) {
18274 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
18276 ArraySizes.push_back(llvm::APSInt::get(1));
18277 Base = TempASE->getBase()->IgnoreParenImpCasts();
18289 return BO_AddAssign;
18291 return BO_MulAssign;
18293 return BO_AndAssign;
18295 return BO_OrAssign;
18297 return BO_XorAssign;
18353 case OO_Array_Delete:
18362 case OO_GreaterEqual:
18364 case OO_MinusEqual:
18366 case OO_SlashEqual:
18367 case OO_PercentEqual:
18368 case OO_CaretEqual:
18372 case OO_GreaterGreater:
18373 case OO_LessLessEqual:
18374 case OO_GreaterGreaterEqual:
18375 case OO_EqualEqual:
18376 case OO_ExclaimEqual:
18379 case OO_MinusMinus:
18385 case OO_Conditional:
18388 llvm_unreachable(
"Unexpected reduction identifier");
18391 if (II->isStr(
"max"))
18393 else if (II->isStr(
"min"))
18401 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
18402 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18405 if (ReductionIdScopeSpec.
isValid())
18411 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18412 bool FirstIter =
true;
18413 for (
Expr *RefExpr : VarList) {
18414 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
18422 if (!FirstIter && IR != ER)
18427 Expr *SimpleRefExpr = RefExpr;
18436 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18437 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18438 Expr *ReductionOp =
nullptr;
18440 (DeclareReductionRef.
isUnset() ||
18441 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get())))
18442 ReductionOp = DeclareReductionRef.
get();
18444 RD.push(RefExpr, ReductionOp);
18450 Expr *TaskgroupDescriptor =
nullptr;
18452 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18453 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18455 Type = ASE->getType().getNonReferenceType();
18460 Type = ATy->getElementType();
18463 Type =
Type.getNonReferenceType();
18467 auto *VD = dyn_cast<VarDecl>(
D);
18473 diag::err_omp_reduction_incomplete_type))
18479 false, ASE || OASE))
18486 if (!ASE && !OASE) {
18488 VarDecl *VDDef = VD->getDefinition();
18490 DSARefChecker Check(Stack);
18491 if (Check.Visit(VDDef->
getInit())) {
18492 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18493 << getOpenMPClauseName(ClauseKind) << ERange;
18511 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18512 if (DVar.CKind == OMPC_reduction) {
18513 S.
Diag(ELoc, diag::err_omp_once_referenced)
18514 << getOpenMPClauseName(ClauseKind);
18516 S.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18519 if (DVar.CKind != OMPC_unknown) {
18520 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18521 << getOpenMPClauseName(DVar.CKind)
18522 << getOpenMPClauseName(OMPC_reduction);
18534 DVar = Stack->getImplicitDSA(
D,
true);
18535 if (DVar.CKind != OMPC_shared) {
18536 S.
Diag(ELoc, diag::err_omp_required_access)
18537 << getOpenMPClauseName(OMPC_reduction)
18538 << getOpenMPClauseName(OMPC_shared);
18546 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18547 if (DVar.CKind == OMPC_threadprivate) {
18548 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18549 << getOpenMPClauseName(DVar.CKind)
18550 << getOpenMPClauseName(OMPC_reduction);
18560 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18561 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18565 (DeclareReductionRef.
isUnset() ||
18566 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get()))) {
18567 RD.push(RefExpr, DeclareReductionRef.
get());
18570 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
18574 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18575 <<
Type << ReductionIdRange;
18578 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18579 <<
Type << ReductionIdRange;
18591 if (DeclareReductionRef.
isUnset()) {
18592 if ((BOK == BO_GT || BOK == BO_LT) &&
18595 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18596 << getOpenMPClauseName(ClauseKind) << S.
getLangOpts().CPlusPlus;
18597 if (!ASE && !OASE) {
18598 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18601 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18606 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18608 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18609 << getOpenMPClauseName(ClauseKind);
18610 if (!ASE && !OASE) {
18611 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18614 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18621 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
18630 bool ConstantLengthOASE =
false;
18632 bool SingleElement;
18635 Context, OASE, SingleElement, ArraySizes);
18638 if (ConstantLengthOASE && !SingleElement) {
18639 for (llvm::APSInt &Size : ArraySizes)
18646 if ((OASE && !ConstantLengthOASE) ||
18648 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18651 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18652 S.
Diag(ELoc, diag::note_vla_unsupported);
18655 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18656 S.
targetDiag(ELoc, diag::note_vla_unsupported);
18669 }
else if (!ASE && !OASE &&
18671 PrivateTy =
D->getType().getNonReferenceType();
18677 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
18682 if (DeclareReductionRef.
isUsable()) {
18684 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18685 if (DRD->getInitializer()) {
18711 Type = ComplexTy->getElementType();
18713 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18720 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18742 llvm::APInt InitValue =
18743 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18744 : llvm::APInt::getMinValue(Size)
18745 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18746 : llvm::APInt::getMaxValue(Size);
18757 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18788 llvm_unreachable(
"Unexpected reduction operation");
18797 }
else if (!
Init) {
18807 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18808 <<
Type << ReductionIdRange;
18809 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18812 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18818 if (DeclareReductionRef.
isUsable()) {
18823 if (!BasePath.empty()) {
18827 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
18830 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
18834 QualType Params[] = {PtrRedTy, PtrRedTy};
18849 CombBOK, LHSDRE, RHSDRE);
18856 if (BOK != BO_LT && BOK != BO_GT) {
18859 BO_Assign, LHSDRE, ReductionOp.
get());
18861 auto *ConditionalOp =
new (Context)
18866 BO_Assign, LHSDRE, ConditionalOp);
18879 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18880 if (ClauseKind == OMPC_reduction &&
18881 RD.RedModifier == OMPC_REDUCTION_inscan) {
18883 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18893 if (Stack->getCurrentDirective() == OMPD_simd ||
18931 if (ClauseKind == OMPC_in_reduction) {
18934 const Expr *ParentReductionOp =
nullptr;
18935 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
18936 DSAStackTy::DSAVarData ParentBOKDSA =
18937 Stack->getTopMostTaskgroupReductionData(
D, ParentSR, ParentBOK,
18939 DSAStackTy::DSAVarData ParentReductionOpDSA =
18940 Stack->getTopMostTaskgroupReductionData(
18941 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
18942 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
18943 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
18944 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
18945 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
18946 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
18947 bool EmitError =
true;
18948 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
18949 llvm::FoldingSetNodeID RedId, ParentRedId;
18950 ParentReductionOp->
Profile(ParentRedId, Context,
true);
18951 DeclareReductionRef.
get()->
Profile(RedId, Context,
18953 EmitError = RedId != ParentRedId;
18957 diag::err_omp_reduction_identifier_mismatch)
18958 << ReductionIdRange << RefExpr->getSourceRange();
18960 diag::note_omp_previous_reduction_identifier)
18962 << (IsParentBOK ? ParentBOKDSA.RefExpr
18963 : ParentReductionOpDSA.RefExpr)
18964 ->getSourceRange();
18968 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
18975 TransformExprToCaptures RebuildToCapture(S,
D);
18977 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
18978 Ref = RebuildToCapture.getCapturedExpr();
18983 RD.ExprCaptures.emplace_back(Ref->
getDecl());
18989 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18994 Stack->getCurrentDirective() == OMPD_taskgroup) {
18995 S.
Diag(RefExpr->getExprLoc(),
18996 diag::err_omp_reduction_non_addressable_expression)
18997 << RefExpr->getSourceRange();
19000 RD.ExprPostUpdates.emplace_back(
19007 unsigned Modifier = RD.RedModifier;
19010 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19011 Modifier = OMPC_REDUCTION_task;
19012 Stack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19014 if (Modifier == OMPC_REDUCTION_task &&
19015 (CurrDir == OMPD_taskgroup ||
19019 if (DeclareReductionRef.
isUsable())
19020 Stack->addTaskgroupReductionData(
D, ReductionIdRange,
19021 DeclareReductionRef.
get());
19023 Stack->addTaskgroupReductionData(
D, ReductionIdRange, BOK);
19025 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
19026 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
19027 TempArrayElem.
get());
19029 return RD.Vars.empty();
19039 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19042 << getOpenMPClauseName(OMPC_reduction);
19050 if (Modifier == OMPC_REDUCTION_inscan &&
19051 (
DSAStack->getCurrentDirective() != OMPD_for &&
19052 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19053 DSAStack->getCurrentDirective() != OMPD_simd &&
19054 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19055 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19056 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19060 ReductionData RD(VarList.size(), Modifier);
19062 StartLoc, LParenLoc, ColonLoc, EndLoc,
19063 ReductionIdScopeSpec, ReductionId,
19064 UnresolvedReductions, RD))
19068 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19071 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19072 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19082 ReductionData RD(VarList.size());
19084 VarList, StartLoc, LParenLoc, ColonLoc,
19085 EndLoc, ReductionIdScopeSpec, ReductionId,
19086 UnresolvedReductions, RD))
19090 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19092 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19102 ReductionData RD(VarList.size());
19104 StartLoc, LParenLoc, ColonLoc, EndLoc,
19105 ReductionIdScopeSpec, ReductionId,
19106 UnresolvedReductions, RD))
19110 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19112 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19121 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19131 const auto *VD = dyn_cast_or_null<VarDecl>(
D);
19134 diag::err_omp_linear_incomplete_type))
19136 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19138 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19142 Type =
Type.getNonReferenceType();
19149 if (!IsDeclareSimd &&
19154 Type =
Type.getUnqualifiedType().getCanonicalType();
19155 const auto *Ty =
Type.getTypePtrOrNull();
19156 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19157 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
19158 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
19160 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19163 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19186 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19188 LinKind = OMPC_LINEAR_val;
19189 for (
Expr *RefExpr : VarList) {
19190 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19193 Expr *SimpleRefExpr = RefExpr;
19197 Vars.push_back(RefExpr);
19198 Privates.push_back(
nullptr);
19199 Inits.push_back(
nullptr);
19206 auto *VD = dyn_cast<VarDecl>(
D);
19212 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
19213 if (DVar.RefExpr) {
19214 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19215 << getOpenMPClauseName(OMPC_linear);
19222 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19228 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
19237 ExprCaptures.push_back(Ref->
getDecl());
19244 SimpleRefExpr, RefRes.
get());
19247 ExprPostUpdates.push_back(
19252 if (LinKind == OMPC_LINEAR_uval)
19253 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19255 InitExpr = VD ? SimpleRefExpr : Ref;
19261 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19263 ? RefExpr->IgnoreParens()
19265 Privates.push_back(PrivateRef);
19266 Inits.push_back(InitRef);
19272 Expr *StepExpr = Step;
19273 Expr *CalcStepExpr =
nullptr;
19281 StepExpr = Val.
get();
19295 if (std::optional<llvm::APSInt>
Result =
19297 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
19298 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19299 << Vars[0] << (Vars.size() > 1);
19303 CalcStepExpr = CalcStep.
get();
19308 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19309 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19315 Expr *NumIterations,
Sema &SemaRef,
19316 Scope *S, DSAStackTy *Stack) {
19328 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19329 bool HasErrors =
false;
19330 auto CurInit = Clause.
inits().begin();
19331 auto CurPrivate = Clause.
privates().begin();
19336 Expr *SimpleRefExpr = RefExpr;
19337 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19339 if (Res.second || !
D) {
19340 Updates.push_back(
nullptr);
19341 Finals.push_back(
nullptr);
19345 auto &&Info = Stack->isLoopControlVariable(
D);
19352 diag::err_omp_linear_distribute_var_non_loop_iteration);
19353 Updates.push_back(
nullptr);
19354 Finals.push_back(
nullptr);
19358 Expr *InitExpr = *CurInit;
19361 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19363 if (LinKind == OMPC_LINEAR_uval)
19364 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19368 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19375 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19386 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19389 Final = *CurPrivate;
19393 if (!
Update.isUsable() || !Final.isUsable()) {
19394 Updates.push_back(
nullptr);
19395 Finals.push_back(
nullptr);
19396 UsedExprs.push_back(
nullptr);
19399 Updates.push_back(
Update.get());
19400 Finals.push_back(Final.get());
19402 UsedExprs.push_back(SimpleRefExpr);
19408 UsedExprs.push_back(S);
19410 UsedExprs.append(Clause.
varlist_size() + 1 - UsedExprs.size(),
nullptr);
19421 for (
Expr *RefExpr : VarList) {
19422 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19425 Expr *SimpleRefExpr = RefExpr;
19429 Vars.push_back(RefExpr);
19436 auto *VD = dyn_cast<VarDecl>(
D);
19444 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19446 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19449 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19456 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(
D, SimpleRefExpr)) {
19457 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19458 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19459 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19460 << getOpenMPClauseName(OMPC_aligned);
19468 .DefaultFunctionArrayConversion(
19469 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19478 if (Alignment !=
nullptr) {
19483 Alignment = AlignResult.
get();
19489 ColonLoc, EndLoc, Vars, Alignment);
19500 for (
Expr *RefExpr : VarList) {
19501 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
19502 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19504 Vars.push_back(RefExpr);
19505 SrcExprs.push_back(
nullptr);
19506 DstExprs.push_back(
nullptr);
19507 AssignmentOps.push_back(
nullptr);
19516 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19517 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19518 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19519 << 0 << RefExpr->getSourceRange();
19523 Decl *
D = DE->getDecl();
19524 auto *VD = cast<VarDecl>(
D);
19529 Vars.push_back(DE);
19530 SrcExprs.push_back(
nullptr);
19531 DstExprs.push_back(
nullptr);
19532 AssignmentOps.push_back(
nullptr);
19538 if (!
DSAStack->isThreadPrivate(VD)) {
19539 Diag(ELoc, diag::err_omp_required_access)
19540 << getOpenMPClauseName(OMPC_copyin)
19541 << getOpenMPDirectiveName(OMPD_threadprivate);
19565 PseudoDstExpr, PseudoSrcExpr);
19574 DSAStack->addDSA(VD, DE, OMPC_copyin);
19575 Vars.push_back(DE);
19576 SrcExprs.push_back(PseudoSrcExpr);
19577 DstExprs.push_back(PseudoDstExpr);
19578 AssignmentOps.push_back(AssignmentOp.
get());
19585 Vars, SrcExprs, DstExprs, AssignmentOps);
19596 for (
Expr *RefExpr : VarList) {
19597 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19600 Expr *SimpleRefExpr = RefExpr;
19604 Vars.push_back(RefExpr);
19605 SrcExprs.push_back(
nullptr);
19606 DstExprs.push_back(
nullptr);
19607 AssignmentOps.push_back(
nullptr);
19614 auto *VD = dyn_cast<VarDecl>(
D);
19619 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
19620 DSAStackTy::DSAVarData DVar =
19622 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19624 Diag(ELoc, diag::err_omp_wrong_dsa)
19625 << getOpenMPClauseName(DVar.CKind)
19626 << getOpenMPClauseName(OMPC_copyprivate);
19634 if (DVar.CKind == OMPC_unknown) {
19635 DVar =
DSAStack->getImplicitDSA(
D,
false);
19636 if (DVar.CKind == OMPC_shared) {
19637 Diag(ELoc, diag::err_omp_required_access)
19638 << getOpenMPClauseName(OMPC_copyprivate)
19639 <<
"threadprivate or private in the enclosing context";
19648 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19649 << getOpenMPClauseName(OMPC_copyprivate) <<
Type
19650 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
19651 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19654 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19675 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19687 VD ? RefExpr->IgnoreParens()
19689 SrcExprs.push_back(PseudoSrcExpr);
19690 DstExprs.push_back(PseudoDstExpr);
19691 AssignmentOps.push_back(AssignmentOp.
get());
19698 EndLoc, Vars, SrcExprs, DstExprs,
19706 if (VarList.empty())
19715 bool Diagnose =
true) {
19716 QualType OMPDependT = Stack->getOMPDependT();
19717 if (!OMPDependT.
isNull())
19723 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
19726 Stack->setOMPDependT(PT.
get());
19747 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19752 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19762struct DoacrossDataInfoTy {
19768 llvm::APSInt TotalDepCount;
19771static DoacrossDataInfoTy
19778 llvm::APSInt DepCounter(32);
19779 llvm::APSInt TotalDepCount(32);
19781 if (
const Expr *OrderedCountExpr =
19782 Stack->getParentOrderedRegionParam().first) {
19783 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
19784 TotalDepCount.setIsUnsigned(
true);
19787 for (
Expr *RefExpr : VarList) {
19788 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
19789 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19791 Vars.push_back(RefExpr);
19798 if (Stack->getParentOrderedRegionParam().first &&
19799 DepCounter >= TotalDepCount) {
19800 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19814 Vars.push_back(RefExpr);
19820 Expr *LHS = SimpleExpr;
19821 Expr *RHS =
nullptr;
19822 if (
auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19824 OOLoc = BO->getOperatorLoc();
19827 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19828 OOK = OCE->getOperator();
19829 OOLoc = OCE->getOperatorLoc();
19832 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19833 OOK = MCE->getMethodDecl()
19836 .getCXXOverloadedOperator();
19837 OOLoc = MCE->getCallee()->getExprLoc();
19846 Vars.push_back(RefExpr);
19852 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
19853 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19859 RHS, OMPC_depend,
false);
19864 Stack->getParentOrderedRegionParam().first &&
19865 DepCounter != Stack->isParentLoopControlVariable(
D).first) {
19867 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19869 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19872 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19876 OpsOffs.emplace_back(RHS, OOK);
19878 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19881 TotalDepCount > VarList.size() &&
19882 Stack->getParentOrderedRegionParam().first &&
19883 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19884 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19885 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19887 return {Vars, OpsOffs, TotalDepCount};
19896 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
19897 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19898 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19899 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19902 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
19903 DepKind == OMPC_DEPEND_mutexinoutset) {
19904 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19907 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
19908 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19910 DepKind == OMPC_DEPEND_sink ||
19912 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19913 DepKind == OMPC_DEPEND_depobj))) {
19915 OMPC_DEPEND_outallmemory,
19916 OMPC_DEPEND_inoutallmemory};
19918 DSAStack->getCurrentDirective() == OMPD_depobj)
19919 Except.push_back(OMPC_DEPEND_depobj);
19921 Except.push_back(OMPC_DEPEND_inoutset);
19923 ?
"depend modifier(iterator) or "
19925 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19929 << getOpenMPClauseName(OMPC_depend);
19933 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
19935 diag::err_omp_depend_sink_source_with_modifier);
19940 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
19944 llvm::APSInt TotalDepCount(32);
19946 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
19949 Vars = VarOffset.Vars;
19950 OpsOffs = VarOffset.OpsOffs;
19951 TotalDepCount = VarOffset.TotalDepCount;
19953 for (
Expr *RefExpr : VarList) {
19954 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
19955 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19957 Vars.push_back(RefExpr);
19963 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
19964 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
19965 if (OMPDependTFound)
19967 DepKind == OMPC_DEPEND_depobj);
19968 if (DepKind == OMPC_DEPEND_depobj) {
19972 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19973 !RefExpr->isInstantiationDependent() &&
19974 !RefExpr->containsUnexpandedParameterPack() &&
19975 (OMPDependTFound &&
19977 DSAStack->getOMPDependT(), RefExpr->getType()))) {
19978 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19979 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
19982 if (!RefExpr->isLValue()) {
19983 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19984 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
19991 QualType ExprTy = RefExpr->getType().getNonReferenceType();
19992 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
19999 ExprTy = ATy->getElementType();
20005 const Expr *Length = OASE->getLength();
20007 if (Length && !Length->isValueDependent() &&
20009 Result.Val.getInt().isZero()) {
20011 diag::err_omp_depend_zero_length_array_section_not_allowed)
20021 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20022 !RefExpr->isInstantiationDependent() &&
20023 !RefExpr->containsUnexpandedParameterPack() &&
20024 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20025 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
20027 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20030 << RefExpr->getSourceRange();
20034 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20035 if (ASE && !ASE->getBase()->isTypeDependent() &&
20038 .getNonReferenceType()
20039 ->isPointerType() &&
20040 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20041 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20044 << RefExpr->getSourceRange();
20052 RefExpr->IgnoreParenImpCasts());
20054 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20055 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20056 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20059 << RefExpr->getSourceRange();
20064 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20068 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20069 DepKind != OMPC_DEPEND_outallmemory &&
20070 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20075 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
20076 TotalDepCount.getZExtValue());
20077 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20078 DSAStack->isParentOrderedRegion())
20079 DSAStack->addDoacrossDependClause(
C, OpsOffs);
20088 "Unexpected device modifier in OpenMP < 50.");
20090 bool ErrorFound =
false;
20092 std::string Values =
20094 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20095 << Values << getOpenMPClauseName(OMPC_device);
20100 Stmt *HelperValStmt =
nullptr;
20113 if (Modifier == OMPC_DEVICE_ancestor) {
20117 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20125 if (CaptureRegion != OMPD_unknown &&
20128 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20129 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20134 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20135 LParenLoc, ModifierLoc, EndLoc);
20140 bool FullCheck =
true) {
20145 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20155 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20160 if (isa<ArraySubscriptExpr>(
E) ||
20161 (OASE && OASE->getColonLocFirst().isInvalid())) {
20162 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20163 return ATy->getSExtSize() != 1;
20168 assert(OASE &&
"Expecting array section if not an array subscript.");
20169 const Expr *LowerBound = OASE->getLowerBound();
20170 const Expr *Length = OASE->getLength();
20179 llvm::APSInt ConstLowerBound =
Result.Val.getInt();
20180 if (ConstLowerBound.getSExtValue())
20195 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
20203 llvm::APSInt ConstLength =
Result.Val.getInt();
20204 return CATy->getSExtSize() != ConstLength.getSExtValue();
20213 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20217 if (isa<ArraySubscriptExpr>(
E) ||
20218 (OASE && OASE->getColonLocFirst().isInvalid()))
20221 assert(OASE &&
"Expecting array section if not an array subscript.");
20222 const Expr *Length = OASE->getLength();
20228 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20229 return ATy->getSExtSize() != 1;
20239 llvm::APSInt ConstLength =
Result.Val.getInt();
20240 return ConstLength.getSExtValue() != 1;
20279class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
20284 bool IsNonContiguous =
false;
20285 bool NoDiagnose =
false;
20286 const Expr *RelevantExpr =
nullptr;
20287 bool AllowUnitySizeArraySection =
true;
20288 bool AllowWholeSizeArraySection =
true;
20289 bool AllowAnotherPtr =
true;
20293 void emitErrorMsg() {
20295 if (SemaRef.getLangOpts().OpenMP < 50) {
20297 diag::err_omp_expected_named_var_member_or_array_expression)
20300 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20301 << getOpenMPClauseName(CKind) << ERange;
20307 if (!isa<VarDecl>(DRE->
getDecl())) {
20311 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20312 RelevantExpr = DRE;
20314 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
20322 if (isa<CXXThisExpr>(BaseE)) {
20323 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20332 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20348 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20368 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20372 return RelevantExpr || Visit(
E);
20382 AllowUnitySizeArraySection =
false;
20383 AllowWholeSizeArraySection =
false;
20386 Components.emplace_back(ME, FD, IsNonContiguous);
20387 return RelevantExpr || Visit(
E);
20395 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20399 return RelevantExpr || Visit(
E);
20406 AllowWholeSizeArraySection =
false;
20412 !Result.Val.getInt().isZero()) {
20414 diag::err_omp_invalid_map_this_expr);
20416 diag::note_omp_invalid_subscript_on_this_ptr_map);
20418 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20423 Components.emplace_back(AE,
nullptr, IsNonContiguous);
20425 return RelevantExpr || Visit(
E);
20431 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20432 "Array sections cannot be implicitly mapped.");
20446 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20456 if (AllowWholeSizeArraySection) {
20463 if (NotWhole || IsPointer)
20464 AllowWholeSizeArraySection =
false;
20465 }
else if (DKind == OMPD_target_update &&
20466 SemaRef.getLangOpts().OpenMP >= 50) {
20467 if (IsPointer && !AllowAnotherPtr)
20468 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20471 IsNonContiguous =
true;
20472 }
else if (AllowUnitySizeArraySection && NotUnity) {
20478 diag::err_array_section_does_not_specify_contiguous_storage)
20484 AllowAnotherPtr =
false;
20486 if (
const auto *TE = dyn_cast<CXXThisExpr>(
E)) {
20493 diag::err_omp_invalid_map_this_expr);
20495 diag::note_omp_invalid_length_on_this_ptr_mapping);
20499 SemaRef.getASTContext()) &&
20502 diag::err_omp_invalid_map_this_expr);
20504 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20506 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20511 Components.emplace_back(OASE,
nullptr,
false);
20512 return RelevantExpr || Visit(
E);
20518 Components.emplace_back(
E,
nullptr, IsNonContiguous);
20520 return Visit(
Base->IgnoreParenImpCasts());
20524 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
20529 if (!RelevantExpr) {
20531 Components.emplace_back(UO,
nullptr,
false);
20547 Components.emplace_back(BO,
nullptr,
false);
20550 "Either LHS or RHS have base decl inside");
20552 return RelevantExpr || Visit(LE);
20553 return RelevantExpr || Visit(RE);
20556 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20557 RelevantExpr = CTE;
20558 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
20562 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20563 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
20567 Expr *Source =
E->getSourceExpr();
20572 return Visit(Source);
20574 bool VisitStmt(
Stmt *) {
20578 const Expr *getFoundBase()
const {
return RelevantExpr; }
20579 explicit MapBaseChecker(
20583 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20584 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20598 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20602 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20603 (CKind == OMPC_to || CKind == OMPC_from)) {
20604 auto CI = CurComponents.rbegin();
20605 auto CE = CurComponents.rend();
20606 for (; CI != CE; ++CI) {
20608 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20613 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
20617 return Checker.getFoundBase();
20626 bool CurrentRegionOnly,
20637 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
20638 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20639 "Map clause expression with unexpected base!");
20642 bool IsEnclosedByDataEnvironmentExpr =
false;
20643 const Expr *EnclosingExpr =
nullptr;
20645 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20646 VD, CurrentRegionOnly,
20647 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20648 ERange, CKind, &EnclosingExpr,
20652 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
20654 assert(!StackComponents.empty() &&
20655 "Map clause expression with no components!");
20656 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20657 "Map clause expression with unexpected base!");
20661 const Expr *RE = StackComponents.front().getAssociatedExpression();
20667 auto CI = CurComponents.rbegin();
20668 auto CE = CurComponents.rend();
20669 auto SI = StackComponents.rbegin();
20670 auto SE = StackComponents.rend();
20671 for (; CI != CE && SI != SE; ++CI, ++SI) {
20676 if (CurrentRegionOnly &&
20677 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20678 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20679 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20680 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20681 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20682 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20683 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20684 diag::err_omp_multiple_array_items_in_map_clause)
20685 << CI->getAssociatedExpression()->getSourceRange();
20686 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20687 diag::note_used_here)
20688 << SI->getAssociatedExpression()->getSourceRange();
20693 if (CI->getAssociatedExpression()->getStmtClass() !=
20694 SI->getAssociatedExpression()->getStmtClass())
20698 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20704 for (; SI != SE; ++SI) {
20706 if (
const auto *ASE =
20707 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20708 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20709 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
20710 SI->getAssociatedExpression())) {
20711 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20712 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20713 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20714 SI->getAssociatedExpression())) {
20715 Type = OASE->getBase()->getType()->getPointeeType();
20719 SemaRef, SI->getAssociatedExpression(),
Type))
20729 if (CI == CE && SI == SE) {
20730 if (CurrentRegionOnly) {
20731 if (CKind == OMPC_map) {
20732 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20734 assert(CKind == OMPC_to || CKind == OMPC_from);
20735 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20744 IsEnclosedByDataEnvironmentExpr =
true;
20749 std::prev(CI)->getAssociatedDeclaration()->getType();
20751 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20770 if (CI == CE || SI == SE) {
20773 diag::err_omp_pointer_mapped_along_with_derived_section)
20779 if (CI->getAssociatedExpression()->getStmtClass() !=
20780 SI->getAssociatedExpression()->getStmtClass() ||
20781 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20782 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20783 assert(CI != CE && SI != SE);
20784 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20797 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20798 if (CKind == OMPC_map) {
20799 if (CI != CE || SI != SE) {
20803 CI != CE ? CurComponents.begin() : StackComponents.begin();
20804 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20806 while (It != End && !It->getAssociatedDeclaration())
20807 std::advance(It, 1);
20808 assert(It != End &&
20809 "Expected at least one component with the declaration.");
20810 if (It !=
Begin && It->getAssociatedDeclaration()
20812 .getCanonicalType()
20813 ->isAnyPointerType()) {
20814 IsEnclosedByDataEnvironmentExpr =
false;
20815 EnclosingExpr =
nullptr;
20819 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20821 assert(CKind == OMPC_to || CKind == OMPC_from);
20822 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20832 if (!CurrentRegionOnly && SI != SE)
20833 EnclosingExpr = RE;
20837 IsEnclosedByDataEnvironmentExpr |=
20838 (!CurrentRegionOnly && CI != CE && SI == SE);
20843 if (CurrentRegionOnly)
20857 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20859 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20875 Expr *UnresolvedMapper) {
20891 while (S && !S->isDeclScope(
D))
20892 S = S->getParent();
20894 S = S->getParent();
20895 Lookups.emplace_back();
20896 Lookups.back().append(Lookup.
begin(), Lookup.
end());
20899 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20903 auto *DMD = cast<OMPDeclareMapperDecl>(
D);
20904 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
20905 Lookups.back().addDecl(DMD);
20913 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
20914 return !D->isInvalidDecl() &&
20915 (D->getType()->isDependentType() ||
20916 D->getType()->isInstantiationDependentType() ||
20917 D->getType()->containsUnexpandedParameterPack());
20928 false, URS.
begin(), URS.
end(),
false,
20936 SemaRef.
Diag(
Loc, diag::err_omp_mapper_wrong_type);
20943 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20953 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20957 !
Type.isMoreQualifiedThan(
D->getType()))
20976 SemaRef.
Diag(
Loc, diag::err_omp_invalid_mapper)
20986struct MappableVarListInfo {
21001 VarComponents.reserve(VarList.size());
21002 VarBaseDeclarations.reserve(VarList.size());
21021 for (
auto *FD : RD->
fields()) {
21029 SExprs.push_back(BE);
21037 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21040 Maps.push_back(MapClause);
21041 return MapperVarRef;
21045 DSAStackTy *Stack) {
21060 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
21062 BaseType, MapperId, Maps,
nullptr);
21068 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21072 DMD->setMapperVarRef(MapperVarRef);
21092 while (S && !S->isDeclScope(
D))
21093 S = S->getParent();
21095 S = S->getParent();
21096 Lookups.emplace_back();
21097 Lookups.back().append(Lookup.
begin(), Lookup.
end());
21103 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
21104 return !D->isInvalidDecl() &&
21105 (D->getType()->isDependentType() ||
21106 D->getType()->isInstantiationDependentType() ||
21107 D->getType()->containsUnexpandedParameterPack());
21114 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21124 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21128 !
Type.isMoreQualifiedThan(
D->getType()))
21137 bool IsAmbiguous = !Paths.isAmbiguous(
21153 {CanonType,
nullptr});
21154 llvm::DenseMap<const Type *, bool>
Visited;
21156 while (!Types.empty()) {
21157 auto [BaseType, CurFD] = Types.pop_back_val();
21158 while (ParentChain.back().second == 0)
21159 ParentChain.pop_back();
21160 --ParentChain.back().second;
21161 if (BaseType.isNull())
21164 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21167 auto It =
Visited.find(BaseType.getTypePtr());
21177 DefaultMapperId, BaseType);
21178 It =
Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21184 bool FirstIter =
true;
21194 ParentChain.emplace_back(CurFD, 1);
21196 ++ParentChain.back().second;
21198 Types.emplace_back(FieldTy, FD);
21217 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
21219 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21220 "Unexpected clause kind with mappable expressions!");
21228 MapperId.
setName(DeclNames.getIdentifier(
21230 MapperId.
setLoc(StartLoc);
21234 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21235 bool UpdateUMIt =
false;
21236 Expr *UnresolvedMapper =
nullptr;
21238 bool HasHoldModifier =
21239 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21247 for (
Expr *RE : MVLI.VarList) {
21248 assert(RE &&
"Null expr in omp to/from/map clause");
21252 if (UpdateUMIt && UMIt != UMEnd) {
21256 "Expect the size of UnresolvedMappers to match with that of VarList");
21260 UnresolvedMapper = *UMIt;
21269 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
21273 MVLI.UDMapperList.push_back(ER.
get());
21276 MVLI.ProcessedVarList.push_back(RE);
21285 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21288 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21301 DSAS->getCurrentDirective(), NoDiagnose);
21305 assert(!CurComponents.empty() &&
21306 "Invalid mappable expression information.");
21308 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21310 DSAS->addMappedClassesQualTypes(TE->getType());
21313 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
21317 MVLI.UDMapperList.push_back(ER.
get());
21319 MVLI.ProcessedVarList.push_back(RE);
21320 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21321 MVLI.VarComponents.back().append(CurComponents.begin(),
21322 CurComponents.end());
21323 MVLI.VarBaseDeclarations.push_back(
nullptr);
21330 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21331 assert(CurDeclaration &&
"Null decl on map clause.");
21334 "Expecting components to have associated only canonical declarations.");
21336 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21337 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21339 assert((VD || FD) &&
"Only variables or fields are expected here!");
21346 if (VD && DSAS->isThreadPrivate(VD)) {
21349 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21350 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21351 << getOpenMPClauseName(CKind);
21365 true, CurComponents, CKind))
21367 if (CKind == OMPC_map &&
21370 false, CurComponents, CKind))
21377 auto I = llvm::find_if(
21382 assert(I != CurComponents.end() &&
"Null decl on map clause.");
21385 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->
IgnoreParens());
21386 auto *OASE = dyn_cast<ArraySectionExpr>(VE->
IgnoreParens());
21387 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->
IgnoreParens());
21389 Type = ASE->getType().getNonReferenceType();
21394 Type = ATy->getElementType();
21397 Type =
Type.getNonReferenceType();
21398 }
else if (OAShE) {
21412 if (CKind == OMPC_map) {
21419 if (DKind == OMPD_target_enter_data &&
21420 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21422 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21423 << (IsMapTypeImplicit ? 1 : 0)
21425 << getOpenMPDirectiveName(DKind);
21434 if (DKind == OMPD_target_exit_data &&
21435 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21436 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
21437 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21438 << (IsMapTypeImplicit ? 1 : 0)
21440 << getOpenMPDirectiveName(DKind);
21449 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21451 SemaRef.
Diag(StartLoc,
21452 diag::err_omp_invalid_map_type_modifier_for_directive)
21454 OMPC_MAP_MODIFIER_ompx_hold)
21455 << getOpenMPDirectiveName(DKind);
21463 if ((DKind == OMPD_target_data ||
21465 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21466 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21467 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21468 << (IsMapTypeImplicit ? 1 : 0)
21470 << getOpenMPDirectiveName(DKind);
21482 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
21484 DKind == OMPD_target)) {
21485 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21487 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21488 << getOpenMPClauseName(DVar.CKind)
21489 << getOpenMPClauseName(OMPC_map)
21490 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21499 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
21500 Type.getCanonicalType(), UnresolvedMapper);
21503 if (!ER.
get() && isa<ArraySectionExpr>(VE)) {
21511 ElemType = ATy->getElementType();
21521 MVLI.UDMapperList.push_back(ER.
get());
21524 MVLI.ProcessedVarList.push_back(RE);
21528 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21534 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21535 MVLI.VarComponents.back().append(CurComponents.begin(),
21536 CurComponents.end());
21537 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ?
nullptr
21557 BuiltinType::OMPIterator))
21559 diag::err_omp_map_modifier_not_iterator);
21562 unsigned Count = 0;
21563 for (
unsigned I = 0,
E = MapTypeModifiers.size(); I <
E; ++I) {
21565 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21566 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21570 "Modifiers exceed the allowed number of map type modifiers");
21571 Modifiers[Count] = MapTypeModifiers[I];
21572 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21576 MappableVarListInfo MVLI(VarList);
21578 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21579 MapType, Modifiers, IsMapTypeImplicit,
21585 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21586 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21588 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21596 if (ReductionType.
isNull())
21604 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21609 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21613 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21617 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21620 return ReductionType;
21626 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21629 Decls.reserve(ReductionTypes.size());
21638 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21640 bool InCompoundScope =
true;
21641 if (S !=
nullptr) {
21650 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21652 while (Filter.hasNext()) {
21653 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21654 if (InCompoundScope) {
21655 auto I = UsedAsPrevious.find(PrevDecl);
21656 if (I == UsedAsPrevious.end())
21657 UsedAsPrevious[PrevDecl] =
false;
21659 UsedAsPrevious[
D] =
true;
21661 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21662 PrevDecl->getLocation();
21665 if (InCompoundScope) {
21666 for (
const auto &PrevData : UsedAsPrevious) {
21667 if (!PrevData.second) {
21668 PrevDRD = PrevData.first;
21673 }
else if (PrevDeclInScope !=
nullptr) {
21674 auto *PrevDRDInScope = PrevDRD =
21675 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21677 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21678 PrevDRDInScope->getLocation();
21679 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21680 }
while (PrevDRDInScope !=
nullptr);
21682 for (
const auto &TyData : ReductionTypes) {
21683 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21685 if (I != PreviousRedeclTypes.end()) {
21686 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21688 Diag(I->second, diag::note_previous_definition);
21691 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21693 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21695 DRD->setAccess(AS);
21696 Decls.push_back(DRD);
21698 DRD->setInvalidDecl();
21708 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21723 QualType ReductionType = DRD->getType();
21740 if (S !=
nullptr) {
21744 DRD->addDecl(OmpInParm);
21745 DRD->addDecl(OmpOutParm);
21751 DRD->setCombinerData(InE, OutE);
21756 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21763 if (Combiner !=
nullptr)
21764 DRD->setCombiner(Combiner);
21766 DRD->setInvalidDecl();
21771 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21785 QualType ReductionType = DRD->getType();
21802 if (S !=
nullptr) {
21806 DRD->addDecl(OmpPrivParm);
21807 DRD->addDecl(OmpOrigParm);
21813 DRD->setInitializerData(OrigE, PrivE);
21814 return OmpPrivParm;
21819 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21828 }
else if (OmpPrivParm->
hasInit()) {
21829 DRD->setInitializer(OmpPrivParm->
getInit(),
21834 DRD->setInvalidDecl();
21840 for (
Decl *
D : DeclReductions.
get()) {
21849 return DeclReductions;
21856 if (
D.isInvalidType())
21869 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
21872 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
21877 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21894 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21896 bool InCompoundScope =
true;
21897 if (S !=
nullptr) {
21906 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21908 while (Filter.hasNext()) {
21909 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21910 if (InCompoundScope) {
21911 auto I = UsedAsPrevious.find(PrevDecl);
21912 if (I == UsedAsPrevious.end())
21913 UsedAsPrevious[PrevDecl] =
false;
21915 UsedAsPrevious[
D] =
true;
21917 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21918 PrevDecl->getLocation();
21921 if (InCompoundScope) {
21922 for (
const auto &PrevData : UsedAsPrevious) {
21923 if (!PrevData.second) {
21924 PrevDMD = PrevData.first;
21929 }
else if (PrevDeclInScope) {
21930 auto *PrevDMDInScope = PrevDMD =
21931 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
21933 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
21934 PrevDMDInScope->getLocation();
21935 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
21936 }
while (PrevDMDInScope !=
nullptr);
21940 if (I != PreviousRedeclTypes.end()) {
21941 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
21942 << MapperType << Name;
21943 Diag(I->second, diag::note_previous_definition);
21951 ClausesWithImplicit);
21953 MapperType, VN, ClausesWithImplicit,
21959 DMD->setAccess(AS);
21961 DMD->setInvalidDecl();
21963 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21967 DMD->setMapperVarRef(MapperVarRef);
21988 if (
DSAStack->getDeclareMapperVarRef())
21993 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
21995 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22008 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22009 return cast<DeclRefExpr>(
DSAStack->getDeclareMapperVarRef())->getDecl();
22016 if (VarList.empty())
22019 for (
Expr *ValExpr : VarList) {
22032 LParenLoc, EndLoc, VarList,
22035 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22037 for (
Expr *ValExpr : VarList) {
22039 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22040 Vars.push_back(ValExpr);
22045 LParenLoc, EndLoc, Vars, PreInit);
22052 if (VarList.empty())
22055 for (
Expr *ValExpr : VarList) {
22068 StartLoc, LParenLoc, EndLoc, VarList,
22071 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22073 for (
Expr *ValExpr : VarList) {
22075 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22076 Vars.push_back(ValExpr);
22081 LParenLoc, EndLoc, Vars, PreInit);
22089 Stmt *HelperValStmt =
nullptr;
22095 ValExpr,
SemaRef, OMPC_priority,
22097 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22101 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22109 "Unexpected grainsize modifier in OpenMP < 51.");
22114 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22115 << Values << getOpenMPClauseName(OMPC_grainsize);
22119 Expr *ValExpr = Grainsize;
22120 Stmt *HelperValStmt =
nullptr;
22130 &CaptureRegion, &HelperValStmt))
22135 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22143 "Unexpected num_tasks modifier in OpenMP < 51.");
22148 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22149 << Values << getOpenMPClauseName(OMPC_num_tasks);
22153 Expr *ValExpr = NumTasks;
22154 Stmt *HelperValStmt =
nullptr;
22161 ValExpr,
SemaRef, OMPC_num_tasks,
22163 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22168 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22188 DSAStackTy *Stack) {
22189 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22190 if (!OMPEventHandleT.
isNull())
22195 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
22198 Stack->setOMPEventHandleT(PT.
get());
22219 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
22229 <<
"omp_event_handle_t" << 1 << VD->
getType()
22236 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
22237 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22240 << getOpenMPClauseName(DVar.CKind)
22241 << getOpenMPClauseName(OMPC_firstprivate);
22256 std::string Values;
22260 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22261 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22264 Expr *ValExpr = ChunkSize;
22265 Stmt *HelperValStmt =
nullptr;
22276 ValExpr = Val.
get();
22281 if (std::optional<llvm::APSInt>
Result =
22283 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
22284 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22289 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22293 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22294 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22302 Kind, ValExpr, HelperValStmt);
22310 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22311 Kind != OMPC_DEFAULTMAP_scalar) {
22315 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22317 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22321 OMPC_DEFAULTMAP_scalar);
22325 Diag(
Loc, diag::err_omp_unexpected_clause_value)
22326 <<
Value << getOpenMPClauseName(OMPC_defaultmap);
22333 if (!isDefaultmapKind || !isDefaultmapModifier) {
22335 ?
"'scalar', 'aggregate', 'pointer'"
22336 :
"'scalar', 'aggregate', 'pointer', 'all'";
22338 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
22339 "'firstprivate', 'none', 'default'";
22340 if (!isDefaultmapKind && isDefaultmapModifier) {
22341 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22342 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22343 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22344 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22345 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22347 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22348 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22349 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22350 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22353 StringRef ModifierValue =
22354 "'alloc', 'from', 'to', 'tofrom', "
22355 "'firstprivate', 'none', 'default', 'present'";
22356 if (!isDefaultmapKind && isDefaultmapModifier) {
22357 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22358 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22359 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22360 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22361 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22363 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22364 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22365 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22366 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22375 if (
DSAStack->checkDefaultmapCategory(Kind)) {
22376 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22382 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22383 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22384 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22386 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22399 !isa<CXXRecordDecl>(CurLexicalContext) &&
22400 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22401 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22402 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22403 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
22409 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
22411 DeclareTargetNesting.push_back(DTCI);
22417 assert(!DeclareTargetNesting.empty() &&
22418 "check isInOpenMPDeclareTargetContext() first!");
22419 return DeclareTargetNesting.pop_back_val();
22429 if (DeclareTargetNesting.empty())
22432 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
22433 << getOpenMPDirectiveName(DTCI.
Kind);
22448 VarOrFuncDeclFilterCCC CCC(
SemaRef);
22459 Diag(
Id.getLoc(), diag::err_undeclared_var_use) <<
Id.getName();
22464 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22465 !isa<FunctionTemplateDecl>(ND)) {
22466 Diag(
Id.getLoc(), diag::err_omp_invalid_target_decl) <<
Id.getName();
22475 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22476 isa<FunctionTemplateDecl>(ND)) &&
22477 "Expected variable, function or function template.");
22479 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
22481 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22482 !VD->isStaticDataMember()) {
22483 Diag(
Loc, diag::err_omp_declare_target_has_local_vars)
22492 Diag(
Loc, diag::warn_omp_declare_target_after_first_use);
22496 Diag(
Loc, diag::warn_hip_omp_target_directives);
22499 const unsigned Level = -1;
22501 auto *VD = cast<ValueDecl>(ND);
22502 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22503 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22504 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
22505 (*ActiveAttr)->getLevel() == Level) {
22506 Diag(
Loc, diag::err_omp_device_type_mismatch)
22507 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
22508 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22509 (*ActiveAttr)->getDevType());
22512 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22513 (*ActiveAttr)->getLevel() == Level) {
22514 Diag(
Loc, diag::err_omp_declare_target_to_and_link) << ND;
22518 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22521 Expr *IndirectE =
nullptr;
22522 bool IsIndirect =
false;
22528 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22533 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22535 if (
auto *VD = dyn_cast<VarDecl>(ND);
22537 VD->hasGlobalStorage())
22543 if (!
D || !isa<VarDecl>(
D))
22545 auto *VD = cast<VarDecl>(
D);
22546 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
22547 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22548 if (SemaRef.
LangOpts.OpenMP >= 50 &&
22551 VD->hasGlobalStorage()) {
22552 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22553 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22560 diag::err_omp_lambda_capture_in_declare_target_not_to);
22561 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
22568 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
22569 SemaRef.
Diag(SL, diag::note_used_here) << SR;
22573 Sema &SemaRef, DSAStackTy *Stack,
22575 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22586 if (
auto *VD = dyn_cast<VarDecl>(
D)) {
22588 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22589 !VD->isStaticDataMember())
22593 if (
DSAStack->isThreadPrivate(VD)) {
22594 Diag(SL, diag::err_omp_threadprivate_in_target);
22599 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(
D))
22600 D = FTD->getTemplatedDecl();
22601 if (
auto *FD = dyn_cast<FunctionDecl>(
D)) {
22602 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22603 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22604 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22605 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22610 if (
auto *VD = dyn_cast<ValueDecl>(
D)) {
22618 if (isa<VarDecl>(
D) || isa<FunctionDecl>(
D) ||
22619 isa<FunctionTemplateDecl>(
D)) {
22620 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22621 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22622 unsigned Level = DeclareTargetNesting.size();
22623 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22626 Expr *IndirectE =
nullptr;
22627 bool IsIndirect =
false;
22633 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22635 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22636 : OMPDeclareTargetDeclAttr::MT_To,
22637 DTCI.
DT, IndirectE, IsIndirect, Level,
22641 ML->DeclarationMarkedOpenMPDeclareTarget(
D, A);
22661 if (
auto *VD = dyn_cast<VarDecl>(
Node->getDecl())) {
22663 DeclVector.push_back(VD);
22668 for (
auto *Child : Ex->
children()) {
22677 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
22678 DeclVector.push_back(cast<VarDecl>(TD));
22679 while (!DeclVector.empty()) {
22680 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22681 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
22695 if (isa<VarDecl>(TargetDecl))
22710 unsigned Count = 0;
22711 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22713 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22714 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22718 "Modifiers exceed the allowed number of motion modifiers");
22719 Modifiers[Count] = MotionModifiers[I];
22720 ModifiersLoc[Count] = MotionModifiersLoc[I];
22724 MappableVarListInfo MVLI(VarList);
22726 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22727 if (MVLI.ProcessedVarList.empty())
22731 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22732 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22747 unsigned Count = 0;
22748 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22750 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22751 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22755 "Modifiers exceed the allowed number of motion modifiers");
22756 Modifiers[Count] = MotionModifiers[I];
22757 ModifiersLoc[Count] = MotionModifiersLoc[I];
22761 MappableVarListInfo MVLI(VarList);
22763 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22764 if (MVLI.ProcessedVarList.empty())
22768 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22769 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22776 MappableVarListInfo MVLI(VarList);
22780 for (
Expr *RefExpr : VarList) {
22781 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
22784 Expr *SimpleRefExpr = RefExpr;
22788 MVLI.ProcessedVarList.push_back(RefExpr);
22789 PrivateCopies.push_back(
nullptr);
22790 Inits.push_back(
nullptr);
22797 Type =
Type.getNonReferenceType().getUnqualifiedType();
22799 auto *VD = dyn_cast<VarDecl>(
D);
22803 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22804 << 0 << RefExpr->getSourceRange();
22812 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
22813 if (VDPrivate->isInvalidDecl())
22818 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22834 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22835 PrivateCopies.push_back(VDPrivateRefExpr);
22836 Inits.push_back(VDInitRefExpr);
22841 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22845 MVLI.VarBaseDeclarations.push_back(
D);
22846 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22847 MVLI.VarComponents.back().emplace_back(SimpleRefExpr,
D,
22851 if (MVLI.ProcessedVarList.empty())
22855 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22856 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22862 MappableVarListInfo MVLI(VarList);
22864 for (
Expr *RefExpr : VarList) {
22865 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
22868 Expr *SimpleRefExpr = RefExpr;
22873 MVLI.ProcessedVarList.push_back(RefExpr);
22878 auto *VD = dyn_cast<VarDecl>(
D);
22885 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22890 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22894 MVLI.VarBaseDeclarations.push_back(
D);
22895 MVLI.VarComponents.emplace_back();
22896 Expr *Component = SimpleRefExpr;
22897 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22898 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22901 MVLI.VarComponents.back().emplace_back(Component,
D,
22905 if (MVLI.ProcessedVarList.empty())
22909 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22910 MVLI.VarComponents);
22916 MappableVarListInfo MVLI(VarList);
22917 for (
Expr *RefExpr : VarList) {
22918 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
22921 Expr *SimpleRefExpr = RefExpr;
22925 MVLI.ProcessedVarList.push_back(RefExpr);
22935 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22936 << 0 << RefExpr->getSourceRange();
22942 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
22944 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22945 << getOpenMPClauseName(DVar.CKind)
22946 << getOpenMPClauseName(OMPC_is_device_ptr)
22947 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
22952 const Expr *ConflictExpr;
22953 if (
DSAStack->checkMappableExprComponentListsForDecl(
22958 ConflictExpr = R.front().getAssociatedExpression();
22961 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22970 SimpleRefExpr,
D,
false);
22971 DSAStack->addMappableExpressionComponents(
22972 D, MC, OMPC_is_device_ptr);
22975 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
22980 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22981 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22982 "Unexpected device pointer expression!");
22983 MVLI.VarBaseDeclarations.push_back(
22984 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
22985 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22986 MVLI.VarComponents.back().push_back(MC);
22989 if (MVLI.ProcessedVarList.empty())
22993 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22994 MVLI.VarComponents);
23000 MappableVarListInfo MVLI(VarList);
23001 for (
Expr *RefExpr : VarList) {
23002 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
23005 Expr *SimpleRefExpr = RefExpr;
23010 MVLI.ProcessedVarList.push_back(RefExpr);
23018 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
23020 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23021 << getOpenMPClauseName(DVar.CKind)
23022 << getOpenMPClauseName(OMPC_has_device_addr)
23023 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
23028 const Expr *ConflictExpr;
23029 if (
DSAStack->checkMappableExprComponentListsForDecl(
23034 ConflictExpr = R.front().getAssociatedExpression();
23037 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23045 Expr *Component = SimpleRefExpr;
23046 auto *VD = dyn_cast<VarDecl>(
D);
23047 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23048 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23052 Component,
D,
false);
23053 DSAStack->addMappableExpressionComponents(
23054 D, MC, OMPC_has_device_addr);
23060 assert(Ref &&
"has_device_addr capture failed");
23061 MVLI.ProcessedVarList.push_back(Ref);
23063 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23068 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23069 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23070 "Unexpected device pointer expression!");
23071 MVLI.VarBaseDeclarations.push_back(
23072 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
23073 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23074 MVLI.VarComponents.back().push_back(MC);
23077 if (MVLI.ProcessedVarList.empty())
23081 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23082 MVLI.VarComponents);
23098 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
23103 Allocator = AllocatorRes.
get();
23116 for (
Expr *RefExpr : VarList) {
23117 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
23120 Expr *SimpleRefExpr = RefExpr;
23124 Vars.push_back(RefExpr);
23130 auto *VD = dyn_cast<VarDecl>(
D);
23135 ? RefExpr->IgnoreParens()
23143 DSAStack->addInnerAllocatorExpr(Allocator);
23145 Allocator, ColonLoc, EndLoc, Vars);
23153 for (
Expr *RefExpr : VarList) {
23154 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23157 Expr *SimpleRefExpr = RefExpr;
23161 Vars.push_back(RefExpr);
23168 if (
const Expr *PrevRef =
23169 DSAStack->addUniqueNontemporal(
D, SimpleRefExpr)) {
23170 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23171 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23172 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23173 << getOpenMPClauseName(OMPC_nontemporal);
23177 Vars.push_back(RefExpr);
23205 for (
Expr *RefExpr : VarList) {
23206 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23209 Expr *SimpleRefExpr = RefExpr;
23214 Vars.push_back(RefExpr);
23219 const DSAStackTy::DSAVarData DVar =
23225 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23226 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23227 << RefExpr->getSourceRange();
23229 if (
DSAStack->getParentDirective() != OMPD_unknown)
23230 DSAStack->markDeclAsUsedInScanDirective(
D);
23231 Vars.push_back(RefExpr);
23246 for (
Expr *RefExpr : VarList) {
23247 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23250 Expr *SimpleRefExpr = RefExpr;
23255 Vars.push_back(RefExpr);
23261 DSAStackTy::DSAVarData DVar;
23262 if (ParentDirective != OMPD_unknown)
23268 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23269 DVar.Modifier != OMPC_REDUCTION_inscan) {
23270 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23271 << RefExpr->getSourceRange();
23273 DSAStack->markDeclAsUsedInScanDirective(
D);
23275 Vars.push_back(RefExpr);
23287 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23288 if (!OMPAlloctraitT.
isNull())
23293 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
23296 Stack->setOMPAlloctraitT(PT.
get());
23316 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23317 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
23318 StringRef Allocator =
23319 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23327 Expr *AllocatorExpr =
nullptr;
23329 if (
D.Allocator->isTypeDependent()) {
23330 AllocatorExpr =
D.Allocator;
23334 AllocatorExpr =
D.Allocator->IgnoreParenImpCasts();
23335 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23336 bool IsPredefinedAllocator =
false;
23338 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23340 IsPredefinedAllocator =
23342 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23346 bool IsTypeCompatible = IsPredefinedAllocator;
23347 IsTypeCompatible = IsTypeCompatible ||
23349 OMPAllocatorHandleT);
23351 IsTypeCompatible ||
23353 bool IsNonConstantLValue =
23355 if (!DRE || !IsTypeCompatible ||
23356 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23357 Diag(
D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23358 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
23365 if (IsPredefinedAllocator &&
D.AllocatorTraits) {
23366 Diag(
D.AllocatorTraits->getExprLoc(),
23367 diag::err_omp_predefined_allocator_with_traits)
23369 Diag(
D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23370 << cast<NamedDecl>(DRE->
getDecl())->getName()
23377 if (!IsPredefinedAllocator && !
D.AllocatorTraits) {
23378 Diag(
D.Allocator->getExprLoc(),
23379 diag::err_omp_nonpredefined_allocator_without_traits);
23383 if (!
D.AllocatorTraits)
23387 IsPredefinedAllocator
23388 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23389 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23391 Expr *AllocatorTraitsExpr =
nullptr;
23392 if (
D.AllocatorTraits) {
23393 if (
D.AllocatorTraits->isTypeDependent()) {
23394 AllocatorTraitsExpr =
D.AllocatorTraits;
23400 AllocatorTraitsExpr =
D.AllocatorTraits->IgnoreParenImpCasts();
23405 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23406 TraitTy = ConstArrayTy->getElementType();
23412 Diag(
D.AllocatorTraits->getExprLoc(),
23413 diag::err_omp_expected_array_alloctraits)
23414 << AllocatorTraitsExpr->
getType();
23419 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23422 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23439 for (
Expr *RefExpr : Locators) {
23440 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
23441 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23443 Vars.push_back(RefExpr);
23451 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23452 << 1 << 0 << RefExpr->getSourceRange();
23461 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23462 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23463 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23464 << 1 << 0 << RefExpr->getSourceRange();
23467 Vars.push_back(SimpleExpr);
23471 ColonLoc, EndLoc, Modifier, Vars);
23480 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23483 << getOpenMPClauseName(OMPC_bind);
23488 LParenLoc, EndLoc);
23495 Expr *ValExpr = Size;
23496 Stmt *HelperValStmt =
nullptr;
23507 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
23508 if (CaptureRegion != OMPD_unknown &&
23511 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23512 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23517 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23525 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
23526 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23527 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23528 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23529 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23530 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23536 llvm::APSInt TotalDepCount(32);
23539 DepType == OMPC_DOACROSS_source ||
23540 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23541 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23543 Vars = VarOffset.Vars;
23544 OpsOffs = VarOffset.OpsOffs;
23545 TotalDepCount = VarOffset.TotalDepCount;
23547 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23548 TotalDepCount.getZExtValue());
23549 if (
DSAStack->isParentOrderedRegion())
23550 DSAStack->addDoacrossDependClause(
C, OpsOffs);
23579 case OMPC_contains:
23582 llvm_unreachable(
"Unexpected OpenMP clause");
23590 case OMPC_no_openmp:
23592 case OMPC_no_openmp_routines:
23594 case OMPC_no_parallelism:
23597 llvm_unreachable(
"Unexpected OpenMP clause");
23606 if (
Base->hasPlaceholderType() &&
23607 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23620 LowerBound =
Result.get();
23622 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23642 if (
Base->isTypeDependent() ||
23645 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23649 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23661 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23662 <<
Base->getSourceRange());
23668 if (Res.isInvalid())
23670 diag::err_omp_typecheck_section_not_integer)
23672 LowerBound = Res.get();
23682 if (Res.isInvalid())
23684 diag::err_omp_typecheck_section_not_integer)
23685 << 1 << Length->getSourceRange());
23686 Length = Res.get();
23688 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23689 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23690 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23691 << 1 << Length->getSourceRange();
23698 diag::err_omp_typecheck_section_not_integer)
23700 Stride = Res.
get();
23713 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
23714 << ResultTy <<
Base->getSourceRange();
23719 diag::err_omp_section_incomplete_type,
Base))
23727 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
23728 if (LowerBoundValue.isNegative()) {
23730 diag::err_omp_section_not_subset_of_array)
23739 if (Length->EvaluateAsInt(
Result, Context)) {
23742 llvm::APSInt LengthValue =
Result.Val.getInt();
23743 if (LengthValue.isNegative()) {
23744 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23745 <<
toString(LengthValue, 10,
true)
23746 << Length->getSourceRange();
23750 }
else if (ColonLocFirst.
isValid() &&
23756 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23766 llvm::APSInt StrideValue =
Result.Val.getInt();
23767 if (!StrideValue.isStrictlyPositive()) {
23768 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
23769 <<
toString(StrideValue, 10,
true)
23776 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23784 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23791 if (
Base->hasPlaceholderType()) {
23805 LParenLoc, RParenLoc, Dims, Brackets);
23807 (!
Base->isTypeDependent() &&
23810 diag::err_omp_non_pointer_type_array_shaping_base)
23811 <<
Base->getSourceRange());
23814 bool ErrorFound =
false;
23815 for (
Expr *Dim : Dims) {
23816 if (Dim->hasPlaceholderType()) {
23818 if (
Result.isInvalid()) {
23823 if (
Result.isInvalid()) {
23829 if (!Dim->isTypeDependent()) {
23832 if (
Result.isInvalid()) {
23834 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23835 << Dim->getSourceRange();
23840 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23845 if (!
Value.isStrictlyPositive()) {
23846 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23848 << Dim->getSourceRange();
23854 NewDims.push_back(Dim);
23859 LParenLoc, RParenLoc, NewDims, Brackets);
23869 bool IsCorrect =
true;
23874 if (!
D.Type.getAsOpaquePtr()) {
23878 DeclTy = Context.
IntTy;
23879 StartLoc =
D.DeclIdentLoc;
23885 bool IsDeclTyDependent = DeclTy->isDependentType() ||
23886 DeclTy->containsUnexpandedParameterPack() ||
23887 DeclTy->isInstantiationDependentType();
23888 if (!IsDeclTyDependent) {
23889 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23892 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23897 if (DeclTy.isConstant(Context)) {
23900 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23908 assert(
D.DeclIdent &&
"Identifier expected.");
23913 D.DeclIdent, DeclTy, TInfo,
SC_None);
23919 RedeclarationKind::ForVisibleRedeclaration);
23941 if (!IsDeclTyDependent &&
Begin && !
Begin->isTypeDependent()) {
23946 Expr *End =
D.Range.End;
23947 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
23950 End = EndRes.
get();
23952 Expr *Step =
D.Range.Step;
23955 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
23960 std::optional<llvm::APSInt>
Result =
23966 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
23972 if (!
Begin || !End || !IsCorrect) {
23988 if (
Decl *ID =
D.IteratorDecl)
23989 ID->setInvalidDecl();
24001 D.Range.End,
D.Range.Begin);
24007 if (
D.Range.Step) {
24018 D.AssignmentLoc, BO_Sub, Res.
get(),
24035 D.AssignmentLoc, BO_Sub,
D.Range.Begin,
D.Range.End);
24049 D.AssignmentLoc, BO_Sub, Res1.
get(),
24064 D.AssignmentLoc, BO_GT,
D.Range.Step,
24089 CounterVD->setImplicit();
24096 if (
D.Range.Step) {
24098 D.AssignmentLoc, BO_Mul,
24108 D.Range.Begin, UpdateRes.
get());
24115 cast<VarDecl>(
D.IteratorDecl)->getType(),
24118 VDRes.
get(), UpdateRes.
get());
24130 D.AssignmentLoc, UO_PreInc, RefRes.
get());
24131 if (!CounterUpdateRes.
isUsable()) {
24137 if (!CounterUpdateRes.
isUsable()) {
24148 Helpers.assign(ID.size(), {});
24153 if (
Decl *ID =
D.IteratorDecl)
24154 ID->setInvalidDecl();
24159 LLoc, RLoc, ID, Helpers);
24164 StringRef AssumptionStr) {
24165 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24168 unsigned BestEditDistance = 3;
24169 StringRef Suggestion;
24170 for (
const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24171 unsigned EditDistance =
24172 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24173 if (EditDistance < BestEditDistance) {
24174 Suggestion = KnownAssumptionIt.getKey();
24175 BestEditDistance = EditDistance;
24179 if (!Suggestion.empty())
24180 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24181 << AssumptionStr << Suggestion;
24183 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown)
24200 :
SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
enum clang::sema::@1655::IndirectLocalPathEntry::EntryKind Kind
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
llvm::DenseSet< const void * > Visited
static const Decl * getCanonicalDecl(const Decl *D)
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.
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 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 OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
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 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 DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
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 std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, StringRef DiagType="")
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 std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude=std::nullopt)
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 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 bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
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)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
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 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 VarDecl * buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, StringRef Name, const AttrVec *Attrs=nullptr, DeclRefExpr *OrigRef=nullptr)
Build a variable declaration for OpenMP loop iteration variable.
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 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=std::nullopt, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
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 propageted 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 checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
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.
static QualType getPointeeType(const MemRegion *R)
Allows QualTypes to be sorted and hence used in maps and sets.
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF)
bool VisitVarDecl(VarDecl *D)
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F)
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.
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
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
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.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const
Return a non-unique reference to the type for a variable array of the specified element type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
CanQualType OMPArrayShapingTy
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
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 getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
CanQualType OMPIteratorTy
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element 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.
CanQualType ArraySectionTy
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,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType BoundMemberTy
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
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.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified=false)
Compatibility predicates used to check assignment expressions.
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
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
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)
A builtin binary operation expression such as "x + y" or "x <= y".
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
static Opcode getOpForCompoundAssignment(Opcode Opc)
bool isRelationalOp() const
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.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
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...
A call to an overloaded operator written using operator syntax.
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.
Represents the this expression in C++.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
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.
SourceLocation getBeginLoc() const LLVM_READONLY
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
QualType withConst() const
Retrieves a version of this type with const applied.
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)
ImplicitParamDecl * getParam(unsigned i) const
Describes the capture of either a variable, or 'this', or variable-length array type.
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 }.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
ConditionalOperator - The ?: ternary operator.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
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
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.
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
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 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)
A reference to a declared variable, function, enum, etc.
SourceLocation getBeginLoc() const LLVM_READONLY
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)
SourceLocation getEndLoc() const LLVM_READONLY
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
SourceLocation getBeginLoc() const LLVM_READONLY
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.
RAII object that enters a new expression evaluation context.
The return type of classify().
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,...
@ 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.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
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, e.g.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
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.
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
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...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
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.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
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.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
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 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.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
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.
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.
A C++ nested-name-specifier augmented with source location information.
static OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
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 OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
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 OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, 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.
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
This represents 'at' clause in the '#pragma omp error' directive.
SourceLocation getAtKindKwLoc() const
Returns location of clause kind.
OpenMPAtClauseKind getAtKind() const
Returns kind of the clause.
This represents 'atomic_default_mem_order' clause in the '#pragma omp requires' directive.
static OMPAtomicDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expressions Exprs)
Creates directive with a list of Clauses and 'x', 'v' and 'expr' parts of the atomic construct (see S...
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
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.
static OMPCanonicalLoop * create(const ASTContext &Ctx, Stmt *LoopStmt, CapturedStmt *DistanceFunc, CapturedStmt *LoopVarFunc, DeclRefExpr *LoopVarRef)
Create a new OMPCanonicalLoop.
This represents 'capture' clause in the '#pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Class that represents a component of a mappable expression.
ValueDecl * getAssociatedDeclaration() const
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.
This represents 'compare' clause in the '#pragma omp atomic' directive.
static OMPContainsClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
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 '#pragma omp critical' directive.
static OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
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 '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.
static OMPDepobjDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
This represents 'destroy' clause in the '#pragma omp depobj' directive or the '#pragma omp interop' d...
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 'dynamic_allocators' clause in the '#pragma omp requires' directive.
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 is a basic class for representing single OpenMP executable directive.
OpenMPDirectiveKind getDirectiveKind() const
This represents 'fail' clause in the '#pragma omp atomic' directive.
This represents 'filter' clause in the '#pragma omp ...' directive.
This represents 'final' clause in the '#pragma omp ...' directive.
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFlushDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPForDirective * 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 OMPForSimdDirective * 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 OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
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.
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.
This represents the 'holds' clause in the '#pragma omp assume' directive.
This represents 'if' clause in the '#pragma omp ...' directive.
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
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 OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the '#pragma omp ...' directives.
Expr * getStep()
Returns linear step.
void setUpdates(ArrayRef< Expr * > UL)
Sets the list of update expressions for linear variables.
privates_range privates()
void setFinals(ArrayRef< Expr * > FL)
Sets the list of final update expressions for linear variables.
void setUsedExprs(ArrayRef< Expr * > UE)
Sets the list of used expressions for the linear clause.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
Expr * getCalcStep()
Returns expression to calculate linear step.
OpenMPLinearClauseKind getModifier() const
Return modifier.
The base class for all loop-based directives, including loop transformation directives.
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
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 OMPMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt)
Creates directive.
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 'mergeable' clause in the '#pragma omp ...' directive.
This represents 'message' clause in the '#pragma omp error' directive.
Expr * getMessageString() const
Returns message string of the clause.
This represents the 'no_openmp' clause in the '#pragma omp assume' directive.
This represents the 'no_openmp_routines' clause in the '#pragma omp assume' directive.
This represents the 'no_parallelism' clause in the '#pragma omp assume' directive.
This represents 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
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 'nowait' 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, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
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.
This represents 'ordered' clause in the '#pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
static OMPOrderedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPParallelDirective * 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 OMPParallelForDirective * 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 OMPParallelForSimdDirective * 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 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 OMPParallelMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
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 OMPParallelMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
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.
static OMPParallelSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
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 represents 'priority' clause in the '#pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents 'read' clause in the '#pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
This represents '#pragma omp requires...' directive.
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp reverse'.
This represents 'reverse_offload' clause in the '#pragma omp requires' directive.
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
This represents 'schedule' clause in the '#pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
static OMPScopeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
static OMPSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
This represents 'seq_cst' clause in the '#pragma omp atomic' directive.
This represents 'severity' clause in the '#pragma omp error' directive.
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPSimdDirective * 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 'simdlen' clause in the '#pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
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 OMPTaskDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, bool HasCancel)
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 OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPTaskgroupDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *ReductionRef)
Creates directive.
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
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 '#pragma omp threadprivate ...' directive.
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > 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, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the '#pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the '#pragma omp requires' directive.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp unroll'.
This represents 'untied' clause in the '#pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
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)
Creates clause with a list of variables Vars.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
SourceLocation getLParenLoc() const
Returns the location of '('.
unsigned varlist_size() const
This represents 'weak' clause in the '#pragma omp atomic' directives.
This represents 'write' clause in the '#pragma omp atomic' directive.
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.
Wrapper for void* pointer.
void * getAsOpaquePtr() const
static OpaquePtr make(PtrTy P)
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
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
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
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
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.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
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 * 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...
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
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...
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
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 en...
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 * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'reduction' 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 * 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'.
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)
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 * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
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.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
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,...
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)
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'from' clause.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
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)
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'to' clause.
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)
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.
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.
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.
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.
OMPClause * ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' 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 state...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
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.
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.
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=std::nullopt)
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'task_reduction' clause.
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...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
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.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
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 * 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.
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 * 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.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
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.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
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 * 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 * 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.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'in_reduction' clause.
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.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
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 on start of '#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.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
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 ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
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.
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
PoppedFunctionScopePtr PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP=nullptr, const Decl *D=nullptr, QualType BlockType=QualType())
Pop a function (or block or lambda or captured region) scope from the stack.
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit=false, bool BuildAndDiagnose=true, const unsigned *const FunctionScopeIndexToStopAt=nullptr, bool ByCopy=false)
Make sure the value of 'this' is actually available in the current context, if it is a potentially ev...
NamedDecl * HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists)
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
FPOptionsOverride CurFPFeatureOverrides()
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt=std::nullopt)
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
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.
void CleanupVarDeclMarking()
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 MarkVariableReferenced(SourceLocation Loc, VarDecl *Var)
Mark a variable referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
void PopExpressionEvaluationContext()
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...
void PushFunctionScope()
Enter a new function scope.
const LangOptions & getLangOpts() const
TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext=nullptr, bool EnteringContext=false, const ObjCObjectPointerType *OPT=nullptr, bool RecordFailure=true)
Try to "correct" a typo in the source code by finding visible declarations whose names are similar to...
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...
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
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.
void CheckExtraCXXDefaultArguments(Declarator &D)
CheckExtraCXXDefaultArguments - Check for any extra default arguments in the declarator,...
const LangOptions & LangOpts
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
DeclContext * getCurLexicalContext() const
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
sema::FunctionScopeInfo * getCurFunction() const
Expr * BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit)
Build a CXXThisExpr and mark it referenced in the current context.
ExprResult DefaultLvalueConversion(Expr *E)
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
@ TryCapture_ExplicitByVal
bool areMultiversionVariantFunctionsCompatible(const FunctionDecl *OldFD, const FunctionDecl *NewFD, const PartialDiagnostic &NoProtoDiagID, const PartialDiagnosticAt &NoteCausedDiagIDAt, const PartialDiagnosticAt &NoSupportDiagIDAt, const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported, bool ConstexprSupported, bool CLinkageMayDiffer)
Checks if the variant/multiversion functions are compatible.
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
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()
RedeclarationKind forRedeclarationInCurContext() const
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),...
TypeSourceInfo * GetTypeForDeclarator(Declarator &D)
GetTypeForDeclarator - Convert the type for the specified declarator to Type instances.
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
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()
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace)
Filters out lookup results that don't fall within the given scope as determined by isDeclInScope.
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)
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
sema::FunctionScopeInfo * getEnclosingFunction() const
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)
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
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 getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
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.
bool isVLASupported() const
Whether target supports variable-length arrays.
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.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
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 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 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
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
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()
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.
Directive - Abstract class representing a parsed verify directive.
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.
void setHasOMPDeclareReductionCombiner()
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.
bool LE(InterpState &S, CodePtr OpPC)
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.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
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
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.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
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.
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
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.
OpenMPGrainsizeClauseModifier
OpenMPNumTasksClauseModifier
ActionResult< Expr * > ExprResult
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
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".
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.
for(const auto &A :T->param_types())
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ActionResult< Decl * > DeclResult
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
bool isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a combined construct for which the first construct is a parallel...
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
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.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Extra information about a function prototype.
llvm::SmallVector< Expr *, 4 > PreferTypes
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.
Expr * ParForInDistCond
'omp parallel for' loop condition used when composed with 'omp distribute' in the same construct and ...
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Expr * LastIteration
Loop last iteration number.
Expr * Cond
Loop condition.
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Expr * IL
IsLastIteration - local flag variable passed to runtime.
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Expr * CalcLastIteration
Calculation of last iteration.
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Expr * ST
Stride - local variable passed to runtime.
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Expr * PreCond
Loop pre-condition.
Stmt * PreInits
Init statement for all captured expressions.
Expr * IterationVarRef
Loop iteration variable.
Expr * NumIterations
Loop number of iterations.
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
void clear(unsigned Size)
Initialize all the fields to null.
Expr * Inc
Loop increment.
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Expr * UB
UpperBound - local variable passed to runtime.
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Expr * LB
LowerBound - local variable passed to runtime.
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Expr * Init
Loop iteration variable init.
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
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.
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Clang specific specialization of the OMPContext to lookup target features.