39#include "llvm/ADT/IndexedMap.h"
40#include "llvm/ADT/PointerEmbeddedInt.h"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/Sequence.h"
43#include "llvm/ADT/SetVector.h"
44#include "llvm/ADT/SmallSet.h"
45#include "llvm/ADT/StringExtras.h"
46#include "llvm/Frontend/OpenMP/OMPAssume.h"
47#include "llvm/Frontend/OpenMP/OMPConstants.h"
48#include "llvm/IR/Assumptions.h"
52using 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 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)
686 SemaRef.
Diag(CPrev->getBeginLoc(),
687 diag::note_omp_requires_previous_clause)
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();
1270 if (
C == OMPC_threadprivate)
1271 return getOpenMPClauseName(
C).str() +
" or thread local";
1272 return getOpenMPClauseName(
C).str();
1275DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &
Iter,
1278 auto *VD = dyn_cast<VarDecl>(
D);
1279 const auto *FD = dyn_cast<FieldDecl>(
D);
1281 if (
Iter == end()) {
1288 DVar.CKind = OMPC_shared;
1295 DVar.CKind = OMPC_shared;
1299 DVar.CKind = OMPC_shared;
1310 DVar.CKind = OMPC_private;
1314 DVar.DKind =
Iter->Directive;
1317 if (
Iter->SharingMap.count(
D)) {
1318 const DSAInfo &
Data =
Iter->SharingMap.lookup(
D);
1319 DVar.RefExpr =
Data.RefExpr.getPointer();
1320 DVar.PrivateCopy =
Data.PrivateCopy;
1321 DVar.CKind =
Data.Attributes;
1322 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1323 DVar.Modifier =
Data.Modifier;
1324 DVar.AppliedToPointee =
Data.AppliedToPointee;
1332 switch (
Iter->DefaultAttr) {
1334 DVar.CKind = OMPC_shared;
1335 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1339 case DSA_firstprivate:
1342 DVar.CKind = OMPC_unknown;
1344 DVar.CKind = OMPC_firstprivate;
1346 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1354 DVar.CKind = OMPC_unknown;
1356 DVar.CKind = OMPC_private;
1358 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1360 case DSA_unspecified:
1365 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1369 DVar.CKind = OMPC_shared;
1379 DSAVarData DVarTemp;
1380 const_iterator I =
Iter,
E = end();
1388 DVarTemp = getDSA(I,
D);
1389 if (DVarTemp.CKind != OMPC_shared) {
1390 DVar.RefExpr =
nullptr;
1391 DVar.CKind = OMPC_firstprivate;
1394 }
while (I !=
E && !isImplicitTaskingRegion(I->Directive));
1396 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1405 return getDSA(++
Iter,
D);
1409 const Expr *NewDE) {
1410 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1412 SharingMapTy &StackElem = getTopOfStack();
1413 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(
D, NewDE);
1415 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1418 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1423 const Expr *NewDE) {
1424 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1426 SharingMapTy &StackElem = getTopOfStack();
1427 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(
D, NewDE);
1429 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1432 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1437 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1439 SharingMapTy &StackElem = getTopOfStack();
1440 StackElem.LCVMap.try_emplace(
1441 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1444const DSAStackTy::LCDeclInfo
1445DSAStackTy::isLoopControlVariable(
const ValueDecl *
D)
const {
1446 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1448 const SharingMapTy &StackElem = getTopOfStack();
1449 auto It = StackElem.LCVMap.find(
D);
1450 if (It != StackElem.LCVMap.end())
1452 return {0,
nullptr};
1455const DSAStackTy::LCDeclInfo
1456DSAStackTy::isLoopControlVariable(
const ValueDecl *
D,
unsigned Level)
const {
1457 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1459 for (
unsigned I = Level + 1; I > 0; --I) {
1460 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1461 auto It = StackElem.LCVMap.find(
D);
1462 if (It != StackElem.LCVMap.end())
1465 return {0,
nullptr};
1468const DSAStackTy::LCDeclInfo
1469DSAStackTy::isParentLoopControlVariable(
const ValueDecl *
D)
const {
1470 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1471 assert(
Parent &&
"Data-sharing attributes stack is empty");
1473 auto It =
Parent->LCVMap.find(
D);
1474 if (It !=
Parent->LCVMap.end())
1476 return {0,
nullptr};
1479const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1480 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1481 assert(
Parent &&
"Data-sharing attributes stack is empty");
1482 if (
Parent->LCVMap.size() < I)
1484 for (
const auto &Pair :
Parent->LCVMap)
1485 if (Pair.second.first == I)
1492 bool AppliedToPointee) {
1494 if (A == OMPC_threadprivate) {
1495 DSAInfo &
Data = Threadprivates[
D];
1496 Data.Attributes = A;
1497 Data.RefExpr.setPointer(
E);
1498 Data.PrivateCopy =
nullptr;
1499 Data.Modifier = Modifier;
1501 DSAInfo &
Data = getTopOfStack().SharingMap[
D];
1502 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1503 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1504 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1505 (isLoopControlVariable(
D).first && A == OMPC_private));
1506 Data.Modifier = Modifier;
1507 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1508 Data.RefExpr.setInt(
true);
1511 const bool IsLastprivate =
1512 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1513 Data.Attributes = A;
1514 Data.RefExpr.setPointerAndInt(
E, IsLastprivate);
1515 Data.PrivateCopy = PrivateCopy;
1516 Data.AppliedToPointee = AppliedToPointee;
1518 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1519 Data.Modifier = Modifier;
1520 Data.Attributes = A;
1521 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1522 Data.PrivateCopy =
nullptr;
1523 Data.AppliedToPointee = AppliedToPointee;
1530 StringRef Name,
const AttrVec *Attrs =
nullptr,
1545 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1552 bool RefersToCapture =
false) {
1563 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1565 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1566 "Additional reduction info may be specified only for reduction items.");
1567 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1568 assert(ReductionData.ReductionRange.isInvalid() &&
1569 (getTopOfStack().
Directive == OMPD_taskgroup ||
1573 "Additional reduction info may be specified only once for reduction "
1575 ReductionData.set(BOK, SR);
1576 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1577 if (!TaskgroupReductionRef) {
1580 TaskgroupReductionRef =
1586 const Expr *ReductionRef) {
1588 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1590 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1591 "Additional reduction info may be specified only for reduction items.");
1592 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1593 assert(ReductionData.ReductionRange.isInvalid() &&
1594 (getTopOfStack().
Directive == OMPD_taskgroup ||
1598 "Additional reduction info may be specified only once for reduction "
1600 ReductionData.set(ReductionRef, SR);
1601 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1602 if (!TaskgroupReductionRef) {
1605 TaskgroupReductionRef =
1610const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1612 Expr *&TaskgroupDescriptor)
const {
1614 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1615 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1616 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1617 if (
Data.Attributes != OMPC_reduction ||
1618 Data.Modifier != OMPC_REDUCTION_task)
1620 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1621 if (!ReductionData.ReductionOp ||
1622 isa<const Expr *>(ReductionData.ReductionOp))
1623 return DSAVarData();
1624 SR = ReductionData.ReductionRange;
1625 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1626 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1627 "expression for the descriptor is not "
1629 TaskgroupDescriptor = I->TaskgroupReductionRef;
1630 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1631 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1634 return DSAVarData();
1637const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1639 Expr *&TaskgroupDescriptor)
const {
1641 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1642 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1643 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1644 if (
Data.Attributes != OMPC_reduction ||
1645 Data.Modifier != OMPC_REDUCTION_task)
1647 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1648 if (!ReductionData.ReductionOp ||
1649 !isa<const Expr *>(ReductionData.ReductionOp))
1650 return DSAVarData();
1651 SR = ReductionData.ReductionRange;
1652 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1653 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1654 "expression for the descriptor is not "
1656 TaskgroupDescriptor = I->TaskgroupReductionRef;
1657 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1658 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1661 return DSAVarData();
1664bool DSAStackTy::isOpenMPLocal(
VarDecl *
D, const_iterator I)
const {
1666 for (const_iterator
E = end(); I !=
E; ++I) {
1667 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1671 Scope *CurScope = getCurScope();
1672 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(
D))
1674 return CurScope != TopScope;
1677 if (I->Context == DC)
1686 bool AcceptIfMutable =
true,
1687 bool *IsClassType =
nullptr) {
1689 Type =
Type.getNonReferenceType().getCanonicalType();
1690 bool IsConstant =
Type.isConstant(Context);
1695 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1697 RD = CTD->getTemplatedDecl();
1700 return IsConstant && !(SemaRef.
getLangOpts().CPlusPlus && RD &&
1707 bool AcceptIfMutable =
true,
1708 bool ListItemNotVar =
false) {
1712 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1713 : IsClassType ? diag::err_omp_const_not_mutable_variable
1714 : diag::err_omp_const_variable;
1716 if (!ListItemNotVar &&
D) {
1717 const VarDecl *VD = dyn_cast<VarDecl>(
D);
1721 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1729const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(
ValueDecl *
D,
1734 auto *VD = dyn_cast<VarDecl>(
D);
1735 auto TI = Threadprivates.find(
D);
1736 if (TI != Threadprivates.end()) {
1737 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1738 DVar.CKind = OMPC_threadprivate;
1739 DVar.Modifier = TI->getSecond().Modifier;
1742 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1744 SemaRef, VD,
D->getType().getNonReferenceType(),
1745 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1746 DVar.CKind = OMPC_threadprivate;
1747 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1754 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1760 SemaRef, VD,
D->getType().getNonReferenceType(),
D->
getLocation());
1761 DVar.CKind = OMPC_threadprivate;
1762 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1767 !isLoopControlVariable(
D).first) {
1768 const_iterator IterTarget =
1769 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1772 if (IterTarget != end()) {
1773 const_iterator ParentIterTarget = IterTarget + 1;
1774 for (const_iterator
Iter = begin();
Iter != ParentIterTarget; ++
Iter) {
1775 if (isOpenMPLocal(VD,
Iter)) {
1779 DVar.CKind = OMPC_threadprivate;
1783 if (!isClauseParsingMode() || IterTarget != begin()) {
1784 auto DSAIter = IterTarget->SharingMap.find(
D);
1785 if (DSAIter != IterTarget->SharingMap.end() &&
1787 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1788 DVar.CKind = OMPC_threadprivate;
1791 const_iterator End = end();
1793 D, std::distance(ParentIterTarget, End),
1797 IterTarget->ConstructLoc);
1798 DVar.CKind = OMPC_threadprivate;
1818 const_iterator I = begin();
1819 const_iterator EndI = end();
1820 if (FromParent && I != EndI)
1823 auto It = I->SharingMap.find(
D);
1824 if (It != I->SharingMap.end()) {
1825 const DSAInfo &
Data = It->getSecond();
1826 DVar.RefExpr =
Data.RefExpr.getPointer();
1827 DVar.PrivateCopy =
Data.PrivateCopy;
1828 DVar.CKind =
Data.Attributes;
1829 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1830 DVar.DKind = I->Directive;
1831 DVar.Modifier =
Data.Modifier;
1832 DVar.AppliedToPointee =
Data.AppliedToPointee;
1837 DVar.CKind = OMPC_shared;
1844 if (SemaRef.
LangOpts.OpenMP <= 31) {
1852 DSAVarData DVarTemp = hasInnermostDSA(
1855 return C == OMPC_firstprivate ||
C == OMPC_shared;
1857 MatchesAlways, FromParent);
1858 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1861 DVar.CKind = OMPC_shared;
1868 const_iterator I = begin();
1869 const_iterator EndI = end();
1870 if (FromParent && I != EndI)
1874 auto It = I->SharingMap.find(
D);
1875 if (It != I->SharingMap.end()) {
1876 const DSAInfo &
Data = It->getSecond();
1877 DVar.RefExpr =
Data.RefExpr.getPointer();
1878 DVar.PrivateCopy =
Data.PrivateCopy;
1879 DVar.CKind =
Data.Attributes;
1880 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1881 DVar.DKind = I->Directive;
1882 DVar.Modifier =
Data.Modifier;
1883 DVar.AppliedToPointee =
Data.AppliedToPointee;
1889const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1890 bool FromParent)
const {
1891 if (isStackEmpty()) {
1893 return getDSA(I,
D);
1896 const_iterator StartI = begin();
1897 const_iterator EndI = end();
1898 if (FromParent && StartI != EndI)
1900 return getDSA(StartI,
D);
1903const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1904 unsigned Level)
const {
1905 if (getStackSize() <= Level)
1906 return DSAVarData();
1908 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1909 return getDSA(StartI,
D);
1912const DSAStackTy::DSAVarData
1915 DefaultDataSharingAttributes)>
1918 bool FromParent)
const {
1922 const_iterator I = begin();
1923 const_iterator EndI = end();
1924 if (FromParent && I != EndI)
1926 for (; I != EndI; ++I) {
1927 if (!DPred(I->Directive) &&
1928 !isImplicitOrExplicitTaskingRegion(I->Directive))
1930 const_iterator NewI = I;
1931 DSAVarData DVar = getDSA(NewI,
D);
1932 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1938const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1941 bool FromParent)
const {
1945 const_iterator StartI = begin();
1946 const_iterator EndI = end();
1947 if (FromParent && StartI != EndI)
1949 if (StartI == EndI || !DPred(StartI->Directive))
1951 const_iterator NewI = StartI;
1952 DSAVarData DVar = getDSA(NewI,
D);
1953 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1958bool DSAStackTy::hasExplicitDSA(
1961 unsigned Level,
bool NotLastprivate)
const {
1962 if (getStackSize() <= Level)
1965 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1966 auto I = StackElem.SharingMap.find(
D);
1967 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1968 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1969 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1972 auto LI = StackElem.LCVMap.find(
D);
1973 if (LI != StackElem.LCVMap.end())
1974 return CPred(OMPC_private,
false);
1978bool DSAStackTy::hasExplicitDirective(
1980 unsigned Level)
const {
1981 if (getStackSize() <= Level)
1983 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1984 return DPred(StackElem.Directive);
1987bool DSAStackTy::hasDirective(
1991 bool FromParent)
const {
1993 size_t Skip = FromParent ? 2 : 1;
1994 for (const_iterator I = begin() + std::min(
Skip, getStackSize()),
E = end();
1996 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2002void SemaOpenMP::InitDataSharingAttributesStack() {
2003 VarDataSharingAttributesStack =
new DSAStackTy(
SemaRef);
2006#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2008void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2016 "Expected OpenMP device compilation.");
2022enum class FunctionEmissionStatus {
2033 "Expected OpenMP device compilation.");
2035 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2040 Kind = SemaDiagnosticBuilder::K_Immediate;
2051 ? SemaDiagnosticBuilder::K_Deferred
2052 : SemaDiagnosticBuilder::K_Immediate;
2056 Kind = SemaDiagnosticBuilder::K_Nop;
2059 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2071 "Expected OpenMP host compilation.");
2073 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2078 Kind = SemaDiagnosticBuilder::K_Immediate;
2081 Kind = SemaDiagnosticBuilder::K_Deferred;
2086 Kind = SemaDiagnosticBuilder::K_Nop;
2096 if (LO.OpenMP <= 45) {
2098 return OMPC_DEFAULTMAP_scalar;
2099 return OMPC_DEFAULTMAP_aggregate;
2102 return OMPC_DEFAULTMAP_pointer;
2104 return OMPC_DEFAULTMAP_scalar;
2105 return OMPC_DEFAULTMAP_aggregate;
2109 unsigned OpenMPCaptureLevel)
const {
2110 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2113 bool IsByRef =
true;
2119 bool IsVariableUsedInMapClause =
false;
2181 bool IsVariableAssociatedWithSection =
false;
2183 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2185 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2192 if (WhereFoundClauseKind != OMPC_map &&
2193 WhereFoundClauseKind != OMPC_has_device_addr)
2196 auto EI = MapExprComponents.rbegin();
2197 auto EE = MapExprComponents.rend();
2199 assert(EI != EE &&
"Invalid map expression!");
2201 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2202 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() ==
D;
2207 auto Last = std::prev(EE);
2209 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2210 if ((UO && UO->getOpcode() == UO_Deref) ||
2211 isa<ArraySubscriptExpr>(
Last->getAssociatedExpression()) ||
2212 isa<ArraySectionExpr>(
Last->getAssociatedExpression()) ||
2213 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2214 isa<OMPArrayShapingExpr>(
Last->getAssociatedExpression())) {
2215 IsVariableAssociatedWithSection =
true;
2224 if (IsVariableUsedInMapClause) {
2227 IsByRef = !(Ty->
isPointerType() && IsVariableAssociatedWithSection);
2232 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2235 DSAStack->isDefaultmapCapturedByRef(
2240 return K == OMPC_reduction && !AppliedToPointee;
2248 ((IsVariableUsedInMapClause &&
2249 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2254 return K == OMPC_firstprivate ||
2255 (K == OMPC_reduction && AppliedToPointee);
2258 DSAStack->isUsesAllocatorsDecl(Level,
D))) &&
2261 !(isa<OMPCapturedExprDecl>(
D) && !
D->
hasAttr<OMPCaptureNoInitAttr>() &&
2262 !cast<OMPCapturedExprDecl>(
D)->getInit()->isGLValue()) &&
2265 !((
DSAStack->getDefaultDSA() == DSA_firstprivate ||
2266 DSAStack->getDefaultDSA() == DSA_private) &&
2270 !
DSAStack->isLoopControlVariable(
D, Level).first);
2287unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2289 return DSAStack->getNestingLevel();
2299 !
DSAStack->isClauseParsingMode()) ||
2310 if (!isa<FieldDecl>(
D))
2312 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2315 DefaultDataSharingAttributes DefaultAttr) {
2317 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2321 if (DVarPrivate.CKind != OMPC_unknown)
2327 Expr *CaptureExpr,
bool WithInit,
2333 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2336 auto *VD = dyn_cast<VarDecl>(
D);
2345 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2355 DSAStackTy::DSAVarData DVarTop =
2357 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2362 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2369 if (!isa<CapturingScopeInfo>(FSI))
2371 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2377 assert(CSI &&
"Failed to find CapturedRegionScopeInfo");
2388 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2394 if (CheckScopeInfo) {
2395 bool OpenMPFound =
false;
2396 for (
unsigned I = StopAt + 1; I > 0; --I) {
2398 if (!isa<CapturingScopeInfo>(FSI))
2400 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2410 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2411 (!
DSAStack->isClauseParsingMode() ||
2412 DSAStack->getParentDirective() != OMPD_unknown)) {
2413 auto &&Info =
DSAStack->isLoopControlVariable(
D);
2416 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2417 (VD &&
DSAStack->isForceVarCapturing()))
2418 return VD ? VD : Info.second;
2419 DSAStackTy::DSAVarData DVarTop =
2421 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2423 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2429 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2437 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2438 ((
DSAStack->getDefaultDSA() != DSA_none &&
2439 DSAStack->getDefaultDSA() != DSA_private &&
2440 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2441 DVarTop.CKind == OMPC_shared))
2443 auto *FD = dyn_cast<FieldDecl>(
D);
2444 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2445 !DVarPrivate.PrivateCopy) {
2446 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2449 DefaultDataSharingAttributes DefaultAttr) {
2451 (DefaultAttr == DSA_firstprivate ||
2452 DefaultAttr == DSA_private);
2456 if (DVarPrivate.CKind == OMPC_unknown)
2479 VD = cast<VarDecl>(VDPrivateRefExpr->
getDecl());
2480 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2483 if (DVarPrivate.CKind != OMPC_unknown ||
2484 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2485 DSAStack->getDefaultDSA() == DSA_private ||
2486 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2487 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2492void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2493 unsigned Level)
const {
2498 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2504 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2506 DSAStack->resetPossibleLoopCounter();
2512 unsigned CapLevel)
const {
2513 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2514 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2515 (!
DSAStack->isClauseParsingMode() ||
2516 DSAStack->getParentDirective() != OMPD_unknown)) {
2517 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2520 DefaultDataSharingAttributes DefaultAttr) {
2522 DefaultAttr == DSA_private;
2526 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(
D) &&
2527 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(
D)) &&
2528 !
DSAStack->isLoopControlVariable(
D).first)
2529 return OMPC_private;
2532 bool IsTriviallyCopyable =
2533 D->getType().getNonReferenceType().isTriviallyCopyableType(
2536 .getNonReferenceType()
2538 ->getAsCXXRecordDecl();
2543 (IsTriviallyCopyable ||
2549 return OMPC_firstprivate;
2550 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2551 if (DVar.CKind != OMPC_shared &&
2552 !
DSAStack->isLoopControlVariable(
D, Level).first && !DVar.RefExpr) {
2553 DSAStack->addImplicitTaskFirstprivate(Level,
D);
2554 return OMPC_firstprivate;
2563 return OMPC_private;
2566 DSAStack->isLoopControlVariable(
D).first) &&
2571 return OMPC_private;
2573 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2579 return OMPC_private;
2584 DSAStack->isUsesAllocatorsDecl(Level,
D).value_or(
2585 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2586 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2587 return OMPC_private;
2591 (
DSAStack->isClauseParsingMode() &&
2592 DSAStack->getClauseParsingMode() == OMPC_private) ||
2597 return K == OMPD_taskgroup ||
2598 ((isOpenMPParallelDirective(K) ||
2599 isOpenMPWorksharingDirective(K)) &&
2600 !isOpenMPSimdDirective(K));
2603 DSAStack->isTaskgroupReductionRef(
D, Level)))
2610 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2613 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2614 const unsigned NewLevel = I - 1;
2618 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2626 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2636 if (
DSAStack->mustBeFirstprivateAtLevel(
2638 OMPC = OMPC_firstprivate;
2642 if (OMPC != OMPC_unknown)
2644 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2648 unsigned CaptureLevel)
const {
2649 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2654 const auto *VD = dyn_cast<VarDecl>(
D);
2658 Regions[CaptureLevel] != OMPD_task;
2662 unsigned CaptureLevel)
const {
2663 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2666 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2670 DSAStackTy::DSAVarData TopDVar =
2672 unsigned NumLevels =
2677 return (NumLevels == CaptureLevel + 1 &&
2678 (TopDVar.CKind != OMPC_shared ||
2679 DSAStack->getDefaultDSA() == DSA_firstprivate));
2682 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2683 if (DVar.CKind != OMPC_shared)
2685 }
while (Level > 0);
2691void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2695 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2700 "Not in OpenMP declare variant scope!");
2702 OMPDeclareVariantScopes.pop_back();
2708 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2709 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2713 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2716 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2717 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2720 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2721 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2722 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2724 StringRef HostDevTy =
2726 Diag(
Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2727 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2728 diag::note_omp_marked_device_type_here)
2734 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2738 for (OMPDeclareVariantAttr *A :
2739 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2740 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2741 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2742 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2743 OMPDeclareTargetDeclAttr::getDeviceType(
2744 VariantFD->getMostRecentDecl());
2745 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2751 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2755 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2756 Diag(
Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2757 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2758 diag::note_omp_marked_device_type_here)
2776 DSAStack->setClauseParsingMode(OMPC_unknown);
2780static std::pair<ValueDecl *, bool>
2782 SourceRange &ERange,
bool AllowArraySection =
false,
2783 StringRef DiagType =
"");
2788 bool InscanFound =
false;
2795 if (
C->getClauseKind() != OMPC_reduction)
2797 auto *RC = cast<OMPReductionClause>(
C);
2798 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2800 InscanLoc = RC->getModifierLoc();
2803 if (RC->getModifier() == OMPC_REDUCTION_task) {
2813 S.
Diag(RC->getModifierLoc(),
2814 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2820 if (
C->getClauseKind() != OMPC_reduction)
2822 auto *RC = cast<OMPReductionClause>(
C);
2823 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2826 : RC->getModifierLoc(),
2827 diag::err_omp_inscan_reduction_expected);
2828 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2831 for (
Expr *Ref : RC->varlist()) {
2832 assert(Ref &&
"NULL expr in OpenMP reduction clause.");
2835 Expr *SimpleRefExpr = Ref;
2842 S.
Diag(Ref->getExprLoc(),
2843 diag::err_omp_reduction_not_inclusive_exclusive)
2844 << Ref->getSourceRange();
2858 const DSAStackTy::DSAVarData &DVar,
2859 bool IsLoopIterVar =
false);
2870 for (
Expr *DE : Clause->varlist()) {
2871 if (DE->isValueDependent() || DE->isTypeDependent()) {
2872 PrivateCopies.push_back(
nullptr);
2875 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2876 auto *VD = cast<VarDecl>(DRE->getDecl());
2878 const DSAStackTy::DSAVarData DVar =
2880 if (DVar.CKind != OMPC_lastprivate) {
2883 PrivateCopies.push_back(
nullptr);
2896 PrivateCopies.push_back(
nullptr);
2902 Clause->setPrivateCopies(PrivateCopies);
2908 for (
Expr *RefExpr : Clause->varlist()) {
2909 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
2912 Expr *SimpleRefExpr = RefExpr;
2916 PrivateRefs.push_back(RefExpr);
2921 const DSAStackTy::DSAVarData DVar =
2923 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2926 Clause->setPrivateRefs(PrivateRefs);
2930 for (
unsigned I = 0,
E = Clause->getNumberOfAllocators(); I <
E; ++I) {
2932 auto *DRE = dyn_cast<DeclRefExpr>(
D.Allocator->IgnoreParenImpCasts());
2936 if (!VD || !isa<VarDecl>(VD))
2938 DSAStackTy::DSAVarData DVar =
2944 Expr *MapExpr =
nullptr;
2946 DSAStack->checkMappableExprComponentListsForDecl(
2952 auto MI = MapExprComponents.rbegin();
2953 auto ME = MapExprComponents.rend();
2955 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2956 VD->getCanonicalDecl()) {
2957 MapExpr = MI->getAssociatedExpression();
2962 Diag(
D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
2967 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2968 << MapExpr->getSourceRange();
2973 if (
const auto *
D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2975 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
2976 FinalizeLastprivate(Clause);
2977 }
else if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
2978 FinalizeNontemporal(Clause);
2979 }
else if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
2980 FinalizeAllocators(Clause);
2995 Expr *NumIterations,
Sema &SemaRef,
2996 Scope *S, DSAStackTy *Stack);
3000 DSAStackTy *Stack) {
3002 "loop exprs were not built");
3009 auto *LC = dyn_cast<OMPLinearClause>(
C);
3028 explicit VarDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3029 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3031 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3039 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3040 return std::make_unique<VarDeclFilterCCC>(*
this);
3049 explicit VarOrFuncDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3050 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3052 if (ND && ((isa<VarDecl>(ND) && ND->
getKind() == Decl::Var) ||
3053 isa<FunctionDecl>(ND))) {
3060 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3061 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3083 VarDeclFilterCCC CCC(
SemaRef);
3090 : diag::err_omp_expected_var_arg_suggest)
3092 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3094 Diag(
Id.getLoc(), Lookup.
empty() ? diag::err_undeclared_var_use
3095 : diag::err_omp_expected_var_arg)
3100 Diag(
Id.getLoc(), diag::err_omp_expected_var_arg) <<
Id.getName();
3109 Diag(
Id.getLoc(), diag::err_omp_global_var_arg)
3110 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->
isStaticLocal();
3114 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3126 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3127 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3131 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3141 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3142 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3146 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3158 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3159 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3163 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3172 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3173 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3177 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3185 if (Kind == OMPD_threadprivate && VD->
isUsed() &&
3187 Diag(
Id.getLoc(), diag::err_omp_var_used)
3188 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3210class LocalVarRefChecker final
3216 if (
const auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3219 diag::err_omp_local_var_in_threadprivate_init)
3221 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3228 bool VisitStmt(
const Stmt *S) {
3229 for (
const Stmt *Child : S->children()) {
3230 if (Child && Visit(Child))
3235 explicit LocalVarRefChecker(
Sema &SemaRef) : SemaRef(SemaRef) {}
3244 for (
Expr *RefExpr : VarList) {
3245 auto *DE = cast<DeclRefExpr>(RefExpr);
3246 auto *VD = cast<VarDecl>(DE->getDecl());
3263 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3271 Diag(ILoc, diag::err_omp_ref_type_arg)
3272 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3277 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3285 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3290 Diag(ILoc, diag::err_omp_var_thread_local)
3295 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3303 LocalVarRefChecker Checker(
SemaRef);
3304 if (Checker.Visit(
Init))
3308 Vars.push_back(RefExpr);
3309 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3310 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3313 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3316 if (!Vars.empty()) {
3324static OMPAllocateDeclAttr::AllocatorTypeTy
3327 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3328 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3329 Allocator->isInstantiationDependent() ||
3330 Allocator->containsUnexpandedParameterPack())
3331 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3332 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3333 llvm::FoldingSetNodeID AEId;
3334 const Expr *AE = Allocator->IgnoreParenImpCasts();
3336 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3337 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3338 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3339 llvm::FoldingSetNodeID DAEId;
3342 if (AEId == DAEId) {
3343 AllocatorKindRes = AllocatorKind;
3347 return AllocatorKindRes;
3352 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3353 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3355 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3356 Expr *PrevAllocator = A->getAllocator();
3357 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3359 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3360 if (AllocatorsMatch &&
3361 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3362 Allocator && PrevAllocator) {
3363 const Expr *AE = Allocator->IgnoreParenImpCasts();
3365 llvm::FoldingSetNodeID AEId, PAEId;
3368 AllocatorsMatch = AEId == PAEId;
3370 if (!AllocatorsMatch) {
3372 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3376 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3378 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3382 Allocator ? Allocator->getExprLoc() : RefExpr->
getExprLoc();
3384 Allocator ? Allocator->getSourceRange() : RefExpr->
getSourceRange();
3386 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3388 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3389 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3390 << (Allocator ? 1 : 0) << AllocatorStream.str()
3391 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3393 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3394 << PrevAllocatorRange;
3402 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3404 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3413 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3414 Allocator->isInstantiationDependent() ||
3415 Allocator->containsUnexpandedParameterPack()))
3417 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3418 Allocator, Alignment, SR);
3421 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3427 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3428 Expr *Alignment =
nullptr;
3429 Expr *Allocator =
nullptr;
3430 if (Clauses.empty()) {
3440 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3441 Allocator = AC->getAllocator();
3442 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3443 Alignment = AC->getAlignment();
3445 llvm_unreachable(
"Unexpected clause on allocate directive");
3447 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3450 for (
Expr *RefExpr : VarList) {
3451 auto *DE = cast<DeclRefExpr>(RefExpr);
3452 auto *VD = cast<VarDecl>(DE->getDecl());
3456 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3464 AllocatorKind, Allocator))
3472 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3473 Diag(Allocator->getExprLoc(),
3474 diag::err_omp_expected_predefined_allocator)
3475 << Allocator->getSourceRange();
3479 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3485 Vars.push_back(RefExpr);
3504 Diag(
Loc, diag::err_omp_invalid_scope) <<
"requires";
3518 bool SkippedClauses) {
3519 if (!SkippedClauses && Assumptions.empty()) {
3521 Diag(
Loc, diag::err_omp_no_clause_for_directive)
3522 << llvm::omp::getAllAssumeClauseOptions()
3523 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3528 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3529 OMPAssumeScoped.push_back(AA);
3534 if (Assumptions.empty())
3537 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3538 "Unexpected omp assumption directive!");
3539 OMPAssumeGlobal.push_back(AA);
3547 while (Ctx->getLexicalParent())
3548 Ctx = Ctx->getLexicalParent();
3549 DeclContexts.push_back(Ctx);
3550 while (!DeclContexts.empty()) {
3552 for (
auto *SubDC : DC->
decls()) {
3553 if (SubDC->isInvalidDecl())
3555 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3556 DeclContexts.push_back(CTD->getTemplatedDecl());
3557 llvm::append_range(DeclContexts, CTD->specializations());
3560 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3561 DeclContexts.push_back(DC);
3562 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3572 OMPAssumeScoped.pop_back();
3593 DSAStack->getEncounteredTargetLocs();
3595 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3596 for (
const OMPClause *CNew : ClauseList) {
3598 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3599 isa<OMPUnifiedAddressClause>(CNew) ||
3600 isa<OMPReverseOffloadClause>(CNew) ||
3601 isa<OMPDynamicAllocatorsClause>(CNew)) {
3602 Diag(
Loc, diag::err_omp_directive_before_requires)
3605 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3609 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3610 Diag(
Loc, diag::err_omp_directive_before_requires)
3612 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3618 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3626 const DSAStackTy::DSAVarData &DVar,
3627 bool IsLoopIterVar) {
3629 SemaRef.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3634 PDSA_StaticMemberShared,
3635 PDSA_StaticLocalVarShared,
3636 PDSA_LoopIterVarPrivate,
3637 PDSA_LoopIterVarLinear,
3638 PDSA_LoopIterVarLastprivate,
3639 PDSA_ConstVarShared,
3640 PDSA_GlobalVarShared,
3641 PDSA_TaskVarFirstprivate,
3642 PDSA_LocalVarPrivate,
3644 } Reason = PDSA_Implicit;
3645 bool ReportHint =
false;
3647 auto *VD = dyn_cast<VarDecl>(
D);
3648 if (IsLoopIterVar) {
3649 if (DVar.CKind == OMPC_private)
3650 Reason = PDSA_LoopIterVarPrivate;
3651 else if (DVar.CKind == OMPC_lastprivate)
3652 Reason = PDSA_LoopIterVarLastprivate;
3654 Reason = PDSA_LoopIterVarLinear;
3656 DVar.CKind == OMPC_firstprivate) {
3657 Reason = PDSA_TaskVarFirstprivate;
3658 ReportLoc = DVar.ImplicitDSALoc;
3660 Reason = PDSA_StaticLocalVarShared;
3662 Reason = PDSA_StaticMemberShared;
3664 Reason = PDSA_GlobalVarShared;
3666 Reason = PDSA_ConstVarShared;
3667 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3669 Reason = PDSA_LocalVarPrivate;
3671 if (Reason != PDSA_Implicit) {
3672 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
3673 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3674 << Reason << ReportHint
3675 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3676 }
else if (DVar.ImplicitDSALoc.isValid()) {
3677 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3684 bool IsAggregateOrDeclareTarget) {
3687 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3688 Kind = OMPC_MAP_alloc;
3690 case OMPC_DEFAULTMAP_MODIFIER_to:
3693 case OMPC_DEFAULTMAP_MODIFIER_from:
3694 Kind = OMPC_MAP_from;
3696 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3697 Kind = OMPC_MAP_tofrom;
3699 case OMPC_DEFAULTMAP_MODIFIER_present:
3705 Kind = OMPC_MAP_alloc;
3707 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3709 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3710 case OMPC_DEFAULTMAP_MODIFIER_none:
3711 case OMPC_DEFAULTMAP_MODIFIER_default:
3716 if (IsAggregateOrDeclareTarget) {
3717 Kind = OMPC_MAP_tofrom;
3720 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3727struct VariableImplicitInfo {
3731 llvm::SetVector<Expr *> Privates;
3732 llvm::SetVector<Expr *> Firstprivates;
3733 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3735 MapModifiers[DefaultmapKindNum];
3738class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3742 bool ErrorFound =
false;
3743 bool TryCaptureCXXThisMembers =
false;
3746 VariableImplicitInfo ImpInfo;
3748 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3752 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3754 if (S->getDirectiveKind() == OMPD_atomic ||
3755 S->getDirectiveKind() == OMPD_critical ||
3756 S->getDirectiveKind() == OMPD_section ||
3757 S->getDirectiveKind() == OMPD_master ||
3758 S->getDirectiveKind() == OMPD_masked ||
3759 S->getDirectiveKind() == OMPD_scope ||
3760 S->getDirectiveKind() == OMPD_assume ||
3762 Visit(S->getAssociatedStmt());
3765 visitSubCaptures(S->getInnermostCapturedStmt());
3768 if (TryCaptureCXXThisMembers ||
3770 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3772 return C.capturesThis();
3774 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3775 TryCaptureCXXThisMembers =
true;
3776 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3777 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3784 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
3785 for (
Expr *Ref : FC->varlist())
3798 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3801 !Stack->getTopDSA(VD,
false).RefExpr &&
3802 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3803 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3804 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3805 Visit(CED->getInit());
3808 }
else if (VD->
isImplicit() || isa<OMPCapturedExprDecl>(VD))
3811 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3816 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3817 !Stack->isImplicitTaskFirstprivate(VD))
3820 if (Stack->isUsesAllocatorsDecl(VD))
3823 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
3825 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3829 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3830 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3833 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3834 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3835 !Stack->isImplicitTaskFirstprivate(VD))
3843 if (DVar.CKind == OMPC_unknown &&
3844 (Stack->getDefaultDSA() == DSA_none ||
3845 Stack->getDefaultDSA() == DSA_private ||
3846 Stack->getDefaultDSA() == DSA_firstprivate) &&
3847 isImplicitOrExplicitTaskingRegion(DKind) &&
3848 VarsWithInheritedDSA.count(VD) == 0) {
3849 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3850 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3851 Stack->getDefaultDSA() == DSA_private)) {
3852 DSAStackTy::DSAVarData DVar =
3853 Stack->getImplicitDSA(VD,
false);
3854 InheritedDSA = DVar.CKind == OMPC_unknown;
3857 VarsWithInheritedDSA[VD] =
E;
3858 if (Stack->getDefaultDSA() == DSA_none)
3873 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3874 OMPC_DEFAULTMAP_MODIFIER_none;
3875 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3876 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3880 if (!Stack->checkMappableExprComponentListsForDecl(
3885 auto MI = MapExprComponents.rbegin();
3886 auto ME = MapExprComponents.rend();
3887 return MI != ME && MI->getAssociatedDeclaration() == VD;
3889 VarsWithInheritedDSA[VD] =
E;
3895 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3896 OMPC_DEFAULTMAP_MODIFIER_present;
3897 if (IsModifierPresent) {
3898 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
3899 OMPC_MAP_MODIFIER_present)) {
3900 ImpInfo.MapModifiers[ClauseKind].push_back(
3901 OMPC_MAP_MODIFIER_present);
3907 !Stack->isLoopControlVariable(VD).first) {
3908 if (!Stack->checkMappableExprComponentListsForDecl(
3913 if (SemaRef.LangOpts.OpenMP >= 50)
3914 return !StackComponents.empty();
3917 return StackComponents.size() == 1 ||
3919 llvm::drop_begin(llvm::reverse(StackComponents)),
3920 [](const OMPClauseMappableExprCommon::
3921 MappableComponent &MC) {
3922 return MC.getAssociatedDeclaration() ==
3924 (isa<ArraySectionExpr>(
3925 MC.getAssociatedExpression()) ||
3926 isa<OMPArrayShapingExpr>(
3927 MC.getAssociatedExpression()) ||
3928 isa<ArraySubscriptExpr>(
3929 MC.getAssociatedExpression()));
3932 bool IsFirstprivate =
false;
3934 if (
const auto *RD =
3936 IsFirstprivate = RD->isLambda();
3938 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3939 if (IsFirstprivate) {
3940 ImpInfo.Firstprivates.insert(
E);
3943 Stack->getDefaultmapModifier(ClauseKind);
3945 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3946 ImpInfo.Mappings[ClauseKind][
Kind].insert(
E);
3956 DVar = Stack->hasInnermostDSA(
3959 return C == OMPC_reduction && !AppliedToPointee;
3968 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
3974 DVar = Stack->getImplicitDSA(VD,
false);
3976 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3977 DVar.CKind == OMPC_firstprivate) ||
3978 (Stack->getDefaultDSA() == DSA_private &&
3979 DVar.CKind == OMPC_private)) &&
3981 !Stack->isLoopControlVariable(VD).first) {
3982 if (Stack->getDefaultDSA() == DSA_private)
3983 ImpInfo.Privates.insert(
E);
3985 ImpInfo.Firstprivates.insert(
E);
3992 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3993 Stack->addToParentTargetRegionLinkGlobals(
E);
4002 auto *FD = dyn_cast<FieldDecl>(
E->getMemberDecl());
4006 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
4009 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4013 !Stack->isLoopControlVariable(FD).first &&
4014 !Stack->checkMappableExprComponentListsForDecl(
4019 return isa<CXXThisExpr>(
4021 StackComponents.back().getAssociatedExpression())
4033 if (Stack->isClassPreviouslyMapped(TE->getType()))
4037 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4042 ImpInfo.Mappings[ClauseKind][
Kind].insert(
E);
4051 DVar = Stack->hasInnermostDSA(
4054 return C == OMPC_reduction && !AppliedToPointee;
4063 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4069 DVar = Stack->getImplicitDSA(FD,
false);
4071 !Stack->isLoopControlVariable(FD).first) {
4076 if (DVar.CKind != OMPC_unknown)
4077 ImpInfo.Firstprivates.insert(
E);
4086 const auto *VD = cast<ValueDecl>(
4087 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4088 if (!Stack->checkMappableExprComponentListsForDecl(
4094 auto CCI = CurComponents.rbegin();
4095 auto CCE = CurComponents.rend();
4096 for (const auto &SC : llvm::reverse(StackComponents)) {
4098 if (CCI->getAssociatedExpression()->getStmtClass() !=
4099 SC.getAssociatedExpression()->getStmtClass())
4100 if (!((isa<ArraySectionExpr>(
4101 SC.getAssociatedExpression()) ||
4102 isa<OMPArrayShapingExpr>(
4103 SC.getAssociatedExpression())) &&
4104 isa<ArraySubscriptExpr>(
4105 CCI->getAssociatedExpression())))
4108 const Decl *CCD = CCI->getAssociatedDeclaration();
4109 const Decl *SCD = SC.getAssociatedDeclaration();
4110 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4111 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4114 std::advance(CCI, 1);
4120 Visit(
E->getBase());
4122 }
else if (!TryCaptureCXXThisMembers) {
4123 Visit(
E->getBase());
4130 if (isa_and_nonnull<OMPPrivateClause>(
C))
4136 if (
C && !((isa<OMPFirstprivateClause>(
C) || isa<OMPMapClause>(
C)) &&
4138 for (
Stmt *CC :
C->children()) {
4145 VisitSubCaptures(S);
4154 for (
Stmt *
C : S->arguments()) {
4161 if (
Expr *Callee = S->getCallee()) {
4162 auto *CI =
Callee->IgnoreParenImpCasts();
4163 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4164 Visit(CE->getBase());
4165 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4169 void VisitStmt(
Stmt *S) {
4170 for (
Stmt *
C : S->children()) {
4181 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4183 VarDecl *VD = Cap.getCapturedVar();
4187 Stack->checkMappableExprComponentListsForDecl(
4194 Cap.getLocation(),
true);
4198 bool isErrorFound()
const {
return ErrorFound; }
4199 const VariableImplicitInfo &getImplicitInfo()
const {
return ImpInfo; }
4201 return VarsWithInheritedDSA;
4205 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4206 DKind = S->getCurrentDirective();
4221 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4223 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4225 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4227 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4229 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4230 Stack->handleConstructTrait(Traits, ScopeEntry);
4241 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4242 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4244 if (LoopBoundSharing) {
4246 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4247 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4251 Params.push_back(std::make_pair(StringRef(),
QualType()));
4272 std::make_pair(
".global_tid.", KmpInt32Ty),
4273 std::make_pair(
".part_id.", KmpInt32PtrTy),
4274 std::make_pair(
".privates.", VoidPtrTy),
4279 std::make_pair(StringRef(),
QualType())
4290 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4293 Params.push_back(std::make_pair(StringRef(),
QualType()));
4300 std::make_pair(StringRef(),
QualType())
4322 std::make_pair(
".global_tid.", KmpInt32Ty),
4323 std::make_pair(
".part_id.", KmpInt32PtrTy),
4324 std::make_pair(
".privates.", VoidPtrTy),
4329 std::make_pair(
".lb.", KmpUInt64Ty),
4330 std::make_pair(
".ub.", KmpUInt64Ty),
4331 std::make_pair(
".st.", KmpInt64Ty),
4332 std::make_pair(
".liter.", KmpInt32Ty),
4333 std::make_pair(
".reductions.", VoidPtrTy),
4334 std::make_pair(StringRef(),
QualType())
4347 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4348 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4351 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4386 case OMPD_metadirective:
4389 llvm_unreachable(
"Unexpected capture region");
4406 case OMPD_interchange:
4419int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4426 return CaptureRegions.size();
4430 Expr *CaptureExpr,
bool WithInit,
4432 bool AsExpression) {
4433 assert(CaptureExpr);
4439 Ty =
C.getLValueReferenceType(Ty);
4441 Ty =
C.getPointerType(Ty);
4453 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4464 CD = cast<OMPCapturedExprDecl>(VD);
4503class CaptureRegionUnwinderRAII {
4510 CaptureRegionUnwinderRAII(
Sema &S,
bool &ErrorFound,
4512 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4513 ~CaptureRegionUnwinderRAII() {
4516 while (--ThisCaptureLevel >= 0)
4529 DSAStack->getCurrentDirective()))) {
4531 if (
const auto *RD =
Type.getCanonicalType()
4532 .getNonReferenceType()
4534 bool SavedForceCaptureByReferenceInTargetExecutable =
4535 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4536 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4538 if (RD->isLambda()) {
4539 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4541 RD->getCaptureFields(Captures, ThisCapture);
4544 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4549 }
else if (LC.getCaptureKind() ==
LCK_This) {
4552 ThisTy, ThisCapture->
getType()))
4557 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4558 SavedForceCaptureByReferenceInTargetExecutable);
4568 for (
const OMPClause *Clause : Clauses) {
4570 Ordered = cast<OMPOrderedClause>(Clause);
4572 Order = cast<OMPOrderClause>(Clause);
4573 if (Order->
getKind() != OMPC_ORDER_concurrent)
4576 if (Ordered && Order)
4580 if (Ordered && Order) {
4582 diag::err_omp_simple_clause_incompatible_with_ordered)
4600 bool ErrorFound =
false;
4601 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4603 if (!S.isUsable()) {
4618 DSAStack->getCurrentDirective() == OMPD_target) &&
4622 auto *IRC = cast<OMPInReductionClause>(Clause);
4623 for (
Expr *
E : IRC->taskgroup_descriptors())
4635 if (
auto *
E = cast_or_null<Expr>(VarRef)) {
4639 DSAStack->setForceVarCapturing(
false);
4640 }
else if (CaptureRegions.size() > 1 ||
4641 CaptureRegions.back() != OMPD_unknown) {
4645 if (
Expr *
E =
C->getPostUpdateExpr())
4650 SC = cast<OMPScheduleClause>(Clause);
4652 OC = cast<OMPOrderedClause>(Clause);
4654 LCs.push_back(cast<OMPLinearClause>(Clause));
4665 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4670 diag::err_omp_simple_clause_incompatible_with_ordered)
4673 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4684 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4694 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(), OMPVersion);
4701 unsigned CompletedRegions = 0;
4706 if (ThisCaptureRegion != OMPD_unknown) {
4714 if (CaptureRegion == ThisCaptureRegion ||
4715 CaptureRegion == OMPD_unknown) {
4716 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4717 for (
Decl *
D : DS->decls())
4724 if (ThisCaptureRegion == OMPD_target) {
4728 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4729 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4732 if (
Expr *
E =
D.AllocatorTraits)
4739 if (ThisCaptureRegion == OMPD_parallel) {
4743 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4744 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4746 for (
Expr *
E : RC->copy_array_temps())
4750 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4751 for (
Expr *
E : AC->varlist())
4756 if (++CompletedRegions == CaptureRegions.size())
4767 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4770 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4771 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4774 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
4775 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4776 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4786 if (!Stack->getCurScope())
4791 bool NestingProhibited =
false;
4792 bool CloseNesting =
true;
4793 bool OrphanSeen =
false;
4796 ShouldBeInParallelRegion,
4797 ShouldBeInOrderedRegion,
4798 ShouldBeInTargetRegion,
4799 ShouldBeInTeamsRegion,
4800 ShouldBeInLoopSimdRegion,
4801 } Recommend = NoRecommend;
4805 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4807 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
4809 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4812 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
4813 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4817 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4818 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4819 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4820 CurrentRegion != OMPD_scan))) {
4833 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
4834 ? diag::err_omp_prohibited_region_simd
4835 : diag::warn_omp_nesting_simd)
4836 << (OMPVersion >= 50 ? 1 : 0);
4837 return CurrentRegion != OMPD_simd;
4839 if (EnclosingConstruct == OMPD_atomic) {
4842 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4845 if (CurrentRegion == OMPD_section) {
4850 if (EnclosingConstruct != OMPD_sections) {
4851 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4852 << (ParentRegion != OMPD_unknown)
4853 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
4861 if (ParentRegion == OMPD_unknown &&
4863 CurrentRegion != OMPD_cancellation_point &&
4864 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4868 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
4869 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4871 EnclosingConstruct == OMPD_loop)) {
4872 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4873 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
4874 <<
true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
4875 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4878 if (CurrentRegion == OMPD_cancellation_point ||
4879 CurrentRegion == OMPD_cancel) {
4892 if (CancelRegion == OMPD_taskgroup) {
4894 EnclosingConstruct != OMPD_task &&
4895 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
4896 }
else if (CancelRegion == OMPD_sections) {
4897 NestingProhibited = EnclosingConstruct != OMPD_section &&
4898 EnclosingConstruct != OMPD_sections;
4900 NestingProhibited = CancelRegion != Leafs.back();
4902 OrphanSeen = ParentRegion == OMPD_unknown;
4903 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4910 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
4916 bool DeadLock = Stack->hasDirective(
4920 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
4921 PreviousCriticalLoc = Loc;
4928 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4930 if (PreviousCriticalLoc.
isValid())
4931 SemaRef.
Diag(PreviousCriticalLoc,
4932 diag::note_omp_previous_critical_region);
4935 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4945 llvm::is_contained({OMPD_masked, OMPD_master,
4946 OMPD_critical, OMPD_ordered},
4947 EnclosingConstruct);
4958 llvm::is_contained({OMPD_masked, OMPD_master,
4959 OMPD_critical, OMPD_ordered},
4960 EnclosingConstruct);
4961 Recommend = ShouldBeInParallelRegion;
4962 }
else if (CurrentRegion == OMPD_ordered) {
4971 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4974 Stack->isParentOrderedRegion());
4975 Recommend = ShouldBeInOrderedRegion;
4981 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
4982 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
4983 EnclosingConstruct != OMPD_target);
4984 OrphanSeen = ParentRegion == OMPD_unknown;
4985 Recommend = ShouldBeInTargetRegion;
4986 }
else if (CurrentRegion == OMPD_scan) {
4987 if (OMPVersion >= 50) {
4992 NestingProhibited = !llvm::is_contained(
4993 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4995 NestingProhibited =
true;
4997 OrphanSeen = ParentRegion == OMPD_unknown;
4998 Recommend = ShouldBeInLoopSimdRegion;
5002 EnclosingConstruct == OMPD_teams) {
5014 CurrentRegion != OMPD_loop &&
5016 CurrentRegion == OMPD_atomic);
5017 Recommend = ShouldBeInParallelRegion;
5019 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5025 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5026 Recommend = ShouldBeInTeamsRegion;
5032 NestingProhibited = EnclosingConstruct != OMPD_teams;
5033 Recommend = ShouldBeInTeamsRegion;
5035 if (!NestingProhibited &&
5042 NestingProhibited = Stack->hasDirective(
5046 OffendingRegion = K;
5052 CloseNesting =
false;
5054 if (NestingProhibited) {
5056 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5057 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5059 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5060 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5061 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5075 bool ErrorFound =
false;
5076 unsigned NamedModifiersNumber = 0;
5077 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5078 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5082 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5086 auto &FNM = FoundNameModifiers[CurNM];
5088 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5089 << getOpenMPDirectiveName(Kind, OMPVersion)
5091 << getOpenMPDirectiveName(CurNM, OMPVersion);
5093 }
else if (CurNM != OMPD_unknown) {
5094 NameModifierLoc.push_back(IC->getNameModifierLoc());
5095 ++NamedModifiersNumber;
5098 if (CurNM == OMPD_unknown)
5104 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5105 S.
Diag(IC->getNameModifierLoc(),
5106 diag::err_omp_wrong_if_directive_name_modifier)
5107 << getOpenMPDirectiveName(CurNM, OMPVersion)
5108 << getOpenMPDirectiveName(Kind, OMPVersion);
5115 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5116 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5117 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5118 diag::err_omp_no_more_if_clause);
5121 std::string Sep(
", ");
5122 unsigned AllowedCnt = 0;
5123 unsigned TotalAllowedNum =
5124 AllowedNameModifiers.size() - NamedModifiersNumber;
5125 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5128 if (!FoundNameModifiers[NM]) {
5130 Values += getOpenMPDirectiveName(NM, OMPVersion);
5132 if (AllowedCnt + 2 == TotalAllowedNum)
5134 else if (AllowedCnt + 1 != TotalAllowedNum)
5139 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5140 diag::err_omp_unnamed_if_clause)
5141 << (TotalAllowedNum > 1) << Values;
5144 S.
Diag(
Loc, diag::note_omp_previous_named_if_clause);
5154 bool AllowArraySection,
5155 StringRef DiagType) {
5158 return std::make_pair(
nullptr,
true);
5170 } IsArrayExpr = NoArrayExpr;
5171 if (AllowArraySection) {
5172 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5173 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5174 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5175 Base = TempASE->getBase()->IgnoreParenImpCasts();
5178 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5179 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5180 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5181 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5182 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5183 Base = TempASE->getBase()->IgnoreParenImpCasts();
5185 IsArrayExpr = OMPArraySection;
5191 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5192 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5193 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5195 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5196 !isa<FieldDecl>(ME->getMemberDecl()))) {
5197 if (IsArrayExpr != NoArrayExpr) {
5198 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5199 << IsArrayExpr << ERange;
5200 }
else if (!DiagType.empty()) {
5204 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5205 << DiagSelect << DiagType << ERange;
5209 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5210 : diag::err_omp_expected_var_name_member_expr)
5213 return std::make_pair(
nullptr,
false);
5215 return std::make_pair(
5222class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5223 DSAStackTy *S =
nullptr;
5227 return S->isUsesAllocatorsDecl(
E->getDecl())
5228 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5229 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5231 bool VisitStmt(
const Stmt *S) {
5232 for (
const Stmt *Child : S->children()) {
5233 if (Child && Visit(Child))
5238 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5245 "Expected non-dependent context.");
5246 auto AllocateRange =
5249 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5254 if (
Cl->getClauseKind() == OMPC_private) {
5255 auto *PC = cast<OMPPrivateClause>(
Cl);
5256 I = PC->private_copies().begin();
5257 It = PC->varlist_begin();
5258 Et = PC->varlist_end();
5259 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5260 auto *PC = cast<OMPFirstprivateClause>(
Cl);
5261 I = PC->private_copies().begin();
5262 It = PC->varlist_begin();
5263 Et = PC->varlist_end();
5264 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5265 auto *PC = cast<OMPLastprivateClause>(
Cl);
5266 I = PC->private_copies().begin();
5267 It = PC->varlist_begin();
5268 Et = PC->varlist_end();
5269 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5270 auto *PC = cast<OMPLinearClause>(
Cl);
5271 I = PC->privates().begin();
5272 It = PC->varlist_begin();
5273 Et = PC->varlist_end();
5274 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5275 auto *PC = cast<OMPReductionClause>(
Cl);
5276 I = PC->privates().begin();
5277 It = PC->varlist_begin();
5278 Et = PC->varlist_end();
5279 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5280 auto *PC = cast<OMPTaskReductionClause>(
Cl);
5281 I = PC->privates().begin();
5282 It = PC->varlist_begin();
5283 Et = PC->varlist_end();
5284 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5285 auto *PC = cast<OMPInReductionClause>(
Cl);
5286 I = PC->privates().begin();
5287 It = PC->varlist_begin();
5288 Et = PC->varlist_end();
5290 llvm_unreachable(
"Expected private clause.");
5292 for (
Expr *
E : llvm::make_range(It, Et)) {
5299 Expr *SimpleRefExpr =
E;
5302 DeclToCopy.try_emplace(Res.first,
5303 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5308 auto *AC = cast<OMPAllocateClause>(
C);
5312 AC->getAllocator()) {
5313 Expr *Allocator = AC->getAllocator();
5319 AllocatorChecker Checker(Stack);
5320 if (Checker.Visit(Allocator))
5321 S.
Diag(Allocator->getExprLoc(),
5322 diag::err_omp_allocator_not_in_uses_allocators)
5323 << Allocator->getSourceRange();
5325 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5331 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5335 S.
Diag(AC->getAllocator()->getExprLoc(),
5336 diag::warn_omp_allocate_thread_on_task_target_directive)
5337 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5339 for (
Expr *
E : AC->varlist()) {
5342 Expr *SimpleRefExpr =
E;
5347 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5350 diag::err_omp_expected_private_copy_for_allocate);
5353 VarDecl *PrivateVD = DeclToCopy[VD];
5355 AllocatorKind, AC->getAllocator()))
5373 CaptureVars(
Sema &Actions) : BaseTransform(Actions) {}
5375 bool AlwaysRebuild() {
return true; }
5388 BodyStmts.push_back(NewDeclStmt);
5426 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5437 auto BuildVarRef = [&](
VarDecl *VD) {
5442 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5444 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5450 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep),
Zero));
5454 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5458 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5462 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5466 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5468 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5472 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5474 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5475 "Expected one of these relational operators");
5482 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5486 if (Rel == BO_GE || Rel == BO_GT)
5488 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5491 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5497 if (Rel == BO_LE || Rel == BO_GE) {
5509 Expr *Divisor = BuildVarRef(NewStep);
5510 if (Rel == BO_GE || Rel == BO_GT)
5513 Expr *DivisorMinusOne =
5518 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5528 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5529 BodyStmts.push_back(ResultAssign);
5534 return cast<CapturedStmt>(
5561 {
"Logical", LogicalTy},
5572 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5577 auto *CS = cast<CapturedDecl>(Actions.
CurContext);
5581 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5584 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5587 CaptureVars Recap(Actions);
5592 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5607 BO_Assign, TargetRef, Advanced));
5609 return cast<CapturedStmt>(
5620 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5622 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5624 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5625 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5627 assert(LCAssign->getOpcode() == BO_Assign &&
5628 "init part must be a loop variable assignment");
5629 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5630 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5632 llvm_unreachable(
"Cannot determine loop variable");
5635 Cond = For->getCond();
5636 Inc = For->getInc();
5637 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5638 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5640 LUVDecl = RangeFor->getLoopVariable();
5642 Cond = RangeFor->getCond();
5643 Inc = RangeFor->getInc();
5645 llvm_unreachable(
"unhandled kind of loop");
5654 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5655 LHS = CondBinExpr->getLHS();
5656 RHS = CondBinExpr->getRHS();
5657 CondRel = CondBinExpr->getOpcode();
5658 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5659 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5660 LHS = CondCXXOp->getArg(0);
5661 RHS = CondCXXOp->getArg(1);
5662 switch (CondCXXOp->getOperator()) {
5663 case OO_ExclaimEqual:
5675 case OO_GreaterEqual:
5679 llvm_unreachable(
"unexpected iterator operator");
5682 llvm_unreachable(
"unexpected loop condition");
5686 cast<DeclRefExpr>(LHS->
IgnoreImplicit())->getDecl() != LIVDecl) {
5687 std::swap(LHS, RHS);
5704 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5706 switch (IncUn->getOpcode()) {
5716 llvm_unreachable(
"unhandled unary increment operator");
5720 llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction,
true),
5722 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5723 if (IncBin->getOpcode() == BO_AddAssign) {
5724 Step = IncBin->getRHS();
5725 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5729 llvm_unreachable(
"unhandled binary increment operator");
5730 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5731 switch (CondCXXOp->getOperator()) {
5734 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5738 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5741 Step = CondCXXOp->getArg(1);
5748 llvm_unreachable(
"unhandled overloaded increment operator");
5751 llvm_unreachable(
"unknown increment expression");
5756 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5759 nullptr,
nullptr, {},
nullptr);
5761 LoopVarFunc, LVRef);
5766 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5773 "Loop transformation directive expected");
5774 return LoopTransform;
5781 Expr *UnresolvedMapper);
5792 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5793 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5797 auto *MI =
C->mapperlist_begin();
5798 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
5818 ElemType = ATy->getElementType();
5821 CanonType = ElemType;
5826 1, {CanonType,
nullptr});
5827 llvm::DenseMap<const Type *, Expr *>
Visited;
5830 while (!Types.empty()) {
5833 std::tie(BaseType, CurFD) = Types.pop_back_val();
5834 while (ParentChain.back().second == 0)
5835 ParentChain.pop_back();
5836 --ParentChain.back().second;
5852 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5863 Expr *BaseExpr = OE;
5864 for (
const auto &
P : ParentChain) {
5882 SubExprs.push_back(BaseExpr);
5886 bool FirstIter =
true;
5896 ParentChain.emplace_back(CurFD, 1);
5898 ++ParentChain.back().second;
5900 Types.emplace_back(FieldTy, FD);
5904 if (SubExprs.empty())
5909 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
5910 MapperIdScopeSpec, MapperId,
C->getMapType(),
5913 Clauses.push_back(NewClause);
5928 if (
D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5930 if (
C->getBindKind() == OMPC_BIND_parallel) {
5931 TeamsLoopCanBeParallelFor =
false;
5936 for (
const Stmt *Child :
D->children())
5946 bool IsOpenMPAPI =
false;
5947 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
5949 std::string Name = FD->getNameInfo().getAsString();
5950 IsOpenMPAPI = Name.find(
"omp_") == 0;
5952 TeamsLoopCanBeParallelFor =
5953 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5954 if (!TeamsLoopCanBeParallelFor)
5957 for (
const Stmt *Child :
C->children())
5965 Visit(S->getCapturedDecl()->getBody());
5968 void VisitStmt(
const Stmt *S) {
5971 for (
const Stmt *Child : S->children())
5975 explicit TeamsLoopChecker(
Sema &SemaRef)
5976 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
5979 bool TeamsLoopCanBeParallelFor;
5984 TeamsLoopChecker Checker(SemaRef);
5985 Checker.Visit(AStmt);
5986 return Checker.teamsLoopCanBeParallelFor();
6000 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6001 BindKind = BC->getBindKind();
6013 BindKind = OMPC_BIND_thread;
6015 getLeafConstructsOrSelf(ParentDirective);
6017 if (ParentDirective == OMPD_unknown) {
6019 diag::err_omp_bind_required_on_loop);
6020 }
else if (ParentLeafs.back() == OMPD_parallel) {
6021 BindKind = OMPC_BIND_parallel;
6022 }
else if (ParentLeafs.back() == OMPD_teams) {
6023 BindKind = OMPC_BIND_teams;
6031 ClausesWithImplicit.push_back(
C);
6035 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6037 if (
C->getClauseKind() == OMPC_reduction)
6039 diag::err_omp_loop_reduction_clause);
6046 BindKind, StartLoc)) {
6053 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6056 bool ErrorFound =
false;
6057 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6061 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
6064 DSAAttrChecker DSAChecker(
DSAStack,
SemaRef, cast<CapturedStmt>(AStmt));
6067 while (--ThisCaptureLevel >= 0)
6068 S = cast<CapturedStmt>(S)->getCapturedStmt();
6069 DSAChecker.Visit(S);
6073 auto *CS = cast<CapturedStmt>(AStmt);
6077 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6079 DSAChecker.visitSubCaptures(CS);
6081 if (DSAChecker.isErrorFound())
6084 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6085 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6088 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6090 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6092 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6093 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6094 PresentModifierLocs[DMC->getDefaultmapKind()] =
6095 DMC->getDefaultmapModifierLoc();
6099 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6101 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6102 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6106 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6107 for (
Expr *
E : IRC->taskgroup_descriptors())
6109 ImpInfo.Firstprivates.insert(
E);
6114 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6115 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6117 if (!ImpInfo.Firstprivates.empty()) {
6121 ClausesWithImplicit.push_back(
Implicit);
6122 ErrorFound = cast<OMPFirstprivateClause>(
Implicit)->varlist_size() !=
6123 ImpInfo.Firstprivates.size();
6128 if (!ImpInfo.Privates.empty()) {
6132 ClausesWithImplicit.push_back(
Implicit);
6133 ErrorFound = cast<OMPPrivateClause>(
Implicit)->varlist_size() !=
6134 ImpInfo.Privates.size();
6143 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6147 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6148 for (
Expr *
E : RC->varlist())
6150 ImplicitExprs.emplace_back(
E);
6152 if (!ImplicitExprs.empty()) {
6158 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6161 ClausesWithImplicit.emplace_back(
Implicit);
6164 for (
unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6165 int ClauseKindCnt = -1;
6166 for (
unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6169 if (ImplicitMap.empty())
6175 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6176 MapperIdScopeSpec, MapperId, K,
true,
6179 ClausesWithImplicit.emplace_back(
Implicit);
6180 ErrorFound |= cast<OMPMapClause>(
Implicit)->varlist_size() !=
6191 ClausesWithImplicit);
6201 VarsWithInheritedDSA);
6216 assert(ClausesWithImplicit.empty() &&
6217 "reverse directive does not support any clauses");
6220 case OMPD_interchange:
6226 VarsWithInheritedDSA);
6230 EndLoc, VarsWithInheritedDSA);
6237 assert(ClausesWithImplicit.empty() &&
6238 "No clauses are allowed for 'omp section' directive");
6246 assert(ClausesWithImplicit.empty() &&
6247 "No clauses are allowed for 'omp master' directive");
6258 case OMPD_parallel_for:
6260 EndLoc, VarsWithInheritedDSA);
6262 case OMPD_parallel_for_simd:
6264 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6270 case OMPD_parallel_master:
6274 case OMPD_parallel_masked:
6278 case OMPD_parallel_sections:
6286 case OMPD_taskyield:
6287 assert(ClausesWithImplicit.empty() &&
6288 "No clauses are allowed for 'omp taskyield' directive");
6289 assert(AStmt ==
nullptr &&
6290 "No associated statement allowed for 'omp taskyield' directive");
6294 assert(AStmt ==
nullptr &&
6295 "No associated statement allowed for 'omp error' directive");
6299 assert(ClausesWithImplicit.empty() &&
6300 "No clauses are allowed for 'omp barrier' directive");
6301 assert(AStmt ==
nullptr &&
6302 "No associated statement allowed for 'omp barrier' directive");
6306 assert(AStmt ==
nullptr &&
6307 "No associated statement allowed for 'omp taskwait' directive");
6310 case OMPD_taskgroup:
6315 assert(AStmt ==
nullptr &&
6316 "No associated statement allowed for 'omp flush' directive");
6320 assert(AStmt ==
nullptr &&
6321 "No associated statement allowed for 'omp depobj' directive");
6325 assert(AStmt ==
nullptr &&
6326 "No associated statement allowed for 'omp scan' directive");
6345 case OMPD_target_parallel:
6349 case OMPD_target_parallel_for:
6351 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6353 case OMPD_cancellation_point:
6354 assert(ClausesWithImplicit.empty() &&
6355 "No clauses are allowed for 'omp cancellation point' directive");
6356 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6357 "cancellation point' directive");
6361 assert(AStmt ==
nullptr &&
6362 "No associated statement allowed for 'omp cancel' directive");
6366 case OMPD_target_data:
6370 case OMPD_target_enter_data:
6374 case OMPD_target_exit_data:
6380 EndLoc, VarsWithInheritedDSA);
6382 case OMPD_taskloop_simd:
6384 EndLoc, VarsWithInheritedDSA);
6386 case OMPD_master_taskloop:
6388 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6390 case OMPD_masked_taskloop:
6392 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6394 case OMPD_master_taskloop_simd:
6396 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6398 case OMPD_masked_taskloop_simd:
6400 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6402 case OMPD_parallel_master_taskloop:
6404 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6406 case OMPD_parallel_masked_taskloop:
6408 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6410 case OMPD_parallel_master_taskloop_simd:
6412 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6414 case OMPD_parallel_masked_taskloop_simd:
6416 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6418 case OMPD_distribute:
6420 EndLoc, VarsWithInheritedDSA);
6422 case OMPD_target_update:
6426 case OMPD_distribute_parallel_for:
6428 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6430 case OMPD_distribute_parallel_for_simd:
6432 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6434 case OMPD_distribute_simd:
6436 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6438 case OMPD_target_parallel_for_simd:
6440 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6442 case OMPD_target_simd:
6444 EndLoc, VarsWithInheritedDSA);
6446 case OMPD_teams_distribute:
6448 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6450 case OMPD_teams_distribute_simd:
6452 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6454 case OMPD_teams_distribute_parallel_for_simd:
6456 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6458 case OMPD_teams_distribute_parallel_for:
6460 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6462 case OMPD_target_teams:
6466 case OMPD_target_teams_distribute:
6468 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6470 case OMPD_target_teams_distribute_parallel_for:
6472 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6474 case OMPD_target_teams_distribute_parallel_for_simd:
6476 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6478 case OMPD_target_teams_distribute_simd:
6480 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6483 assert(AStmt ==
nullptr &&
6484 "No associated statement allowed for 'omp interop' directive");
6493 EndLoc, VarsWithInheritedDSA);
6495 case OMPD_teams_loop:
6497 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6499 case OMPD_target_teams_loop:
6501 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6503 case OMPD_parallel_loop:
6505 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6507 case OMPD_target_parallel_loop:
6509 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6511 case OMPD_declare_target:
6512 case OMPD_end_declare_target:
6513 case OMPD_threadprivate:
6515 case OMPD_declare_reduction:
6516 case OMPD_declare_mapper:
6517 case OMPD_declare_simd:
6519 case OMPD_declare_variant:
6520 case OMPD_begin_declare_variant:
6521 case OMPD_end_declare_variant:
6522 llvm_unreachable(
"OpenMP Directive is not allowed");
6525 llvm_unreachable(
"Unknown OpenMP directive");
6528 ErrorFound = Res.
isInvalid() || ErrorFound;
6532 if (
DSAStack->getDefaultDSA() == DSA_none ||
6533 DSAStack->getDefaultDSA() == DSA_private ||
6534 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6537 switch (
C->getClauseKind()) {
6538 case OMPC_num_threads:
6539 case OMPC_dist_schedule:
6546 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_target)
6550 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_parallel)
6556 case OMPC_grainsize:
6557 case OMPC_num_tasks:
6560 case OMPC_novariants:
6561 case OMPC_nocontext:
6568 case OMPC_num_teams:
6569 case OMPC_thread_limit:
6576 case OMPC_proc_bind:
6578 case OMPC_firstprivate:
6579 case OMPC_lastprivate:
6581 case OMPC_reduction:
6582 case OMPC_task_reduction:
6583 case OMPC_in_reduction:
6587 case OMPC_copyprivate:
6590 case OMPC_mergeable:
6607 case OMPC_defaultmap:
6610 case OMPC_use_device_ptr:
6611 case OMPC_use_device_addr:
6612 case OMPC_is_device_ptr:
6613 case OMPC_has_device_addr:
6614 case OMPC_nontemporal:
6617 case OMPC_inclusive:
6618 case OMPC_exclusive:
6619 case OMPC_uses_allocators:
6626 case OMPC_allocator:
6629 case OMPC_threadprivate:
6632 case OMPC_unified_address:
6633 case OMPC_unified_shared_memory:
6634 case OMPC_reverse_offload:
6635 case OMPC_dynamic_allocators:
6636 case OMPC_atomic_default_mem_order:
6637 case OMPC_self_maps:
6638 case OMPC_device_type:
6643 llvm_unreachable(
"Unexpected clause");
6645 for (
Stmt *CC :
C->children()) {
6647 DSAChecker.Visit(CC);
6650 for (
const auto &
P : DSAChecker.getVarsWithInheritedDSA())
6651 VarsWithInheritedDSA[
P.getFirst()] =
P.getSecond();
6653 for (
const auto &
P : VarsWithInheritedDSA) {
6654 if (
P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(
P.getFirst()))
6657 if (
DSAStack->getDefaultDSA() == DSA_none ||
6658 DSAStack->getDefaultDSA() == DSA_private ||
6659 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6660 Diag(
P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6661 <<
P.first <<
P.second->getSourceRange();
6662 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6664 Diag(
P.second->getExprLoc(),
6665 diag::err_omp_defaultmap_no_attr_for_variable)
6666 <<
P.first <<
P.second->getSourceRange();
6668 diag::note_omp_defaultmap_attr_none);
6674 if (isAllowedClauseForDirective(
D, OMPC_if,
getLangOpts().OpenMP))
6675 AllowedNameModifiers.push_back(
D);
6677 if (!AllowedNameModifiers.empty())
6691 DSAStack->addTargetDirLocation(StartLoc);
6702 assert(Aligneds.size() == Alignments.size());
6703 assert(Linears.size() == LinModifiers.size());
6704 assert(Linears.size() == Steps.size());
6705 if (!DG || DG.
get().isNull())
6708 const int SimdId = 0;
6709 if (!DG.
get().isSingleDecl()) {
6710 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6714 Decl *ADecl = DG.
get().getSingleDecl();
6715 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6716 ADecl = FTD->getTemplatedDecl();
6718 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6720 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6736 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6737 const Expr *UniformedLinearThis =
nullptr;
6738 for (
const Expr *
E : Uniforms) {
6740 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6741 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6742 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6743 FD->getParamDecl(PVD->getFunctionScopeIndex())
6745 UniformedArgs.try_emplace(PVD->getCanonicalDecl(),
E);
6748 if (isa<CXXThisExpr>(
E)) {
6749 UniformedLinearThis =
E;
6753 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6763 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6764 const Expr *AlignedThis =
nullptr;
6765 for (
const Expr *
E : Aligneds) {
6767 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6768 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6770 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6771 FD->getParamDecl(PVD->getFunctionScopeIndex())
6775 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD,
E);
6780 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6785 .getNonReferenceType()
6786 .getUnqualifiedType()
6787 .getCanonicalType();
6792 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6797 if (isa<CXXThisExpr>(
E)) {
6809 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6816 for (
Expr *
E : Alignments) {
6820 NewAligns.push_back(Align.
get());
6831 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6832 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
6833 auto MI = LinModifiers.begin();
6834 for (
const Expr *
E : Linears) {
6838 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6839 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6841 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6842 FD->getParamDecl(PVD->getFunctionScopeIndex())
6846 if (
auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
6851 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6856 if (
auto It = UniformedArgs.find(CanonPVD);
6857 It != UniformedArgs.end()) {
6862 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6866 LinearArgs[CanonPVD] =
E;
6872 PVD->getOriginalType(),
6877 if (isa<CXXThisExpr>(
E)) {
6878 if (UniformedLinearThis) {
6884 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
6889 UniformedLinearThis =
E;
6898 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6900 Expr *Step =
nullptr;
6901 Expr *NewStep =
nullptr;
6903 for (
Expr *
E : Steps) {
6905 if (Step ==
E || !
E) {
6906 NewSteps.push_back(
E ? NewStep :
nullptr);
6910 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6911 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6913 if (UniformedArgs.count(CanonPVD) == 0) {
6920 NewSteps.push_back(Step);
6939 NewSteps.push_back(NewStep);
6941 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6943 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
6944 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
6945 const_cast<Expr **
>(Linears.data()), Linears.size(),
6946 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
6947 NewSteps.data(), NewSteps.size(), SR);
6957 "Unexpected directive category");
6966 llvm_unreachable(
"Unknown OpenMP directive");
6975 "Expected function type with prototype.");
6977 "Expected function with type with no prototype.");
6979 "Expected function with prototype.");
6987 Param->setScopeInfo(0, Params.size());
6988 Param->setImplicit();
6989 Params.push_back(Param);
6992 FD->setParams(Params);
6999 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
7000 FD = UTemplDecl->getTemplatedDecl();
7002 FD = cast<FunctionDecl>(
D);
7003 assert(FD &&
"Expected a function declaration!");
7009 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7012 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7016SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7017 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7022 if (!
D.getIdentifier())
7025 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7028 bool IsTemplated = !TemplateParamLists.empty();
7030 !DVScope.TI->isExtensionActive(
7031 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7048 for (
auto *Candidate : Lookup) {
7049 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7051 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7052 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7053 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7054 UDecl = FTD->getTemplatedDecl();
7055 }
else if (!IsTemplated)
7056 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7070 FType, UDeclTy,
false,
7077 Bases.push_back(UDecl);
7080 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7081 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7083 if (Bases.empty() && UseImplicitBase) {
7087 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7088 Bases.push_back(BaseTemplD->getTemplatedDecl());
7090 Bases.push_back(cast<FunctionDecl>(BaseD));
7093 std::string MangledName;
7094 MangledName +=
D.getIdentifier()->getName();
7096 MangledName += DVScope.NameSuffix;
7111 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
7112 FD = UTemplDecl->getTemplatedDecl();
7114 FD = cast<FunctionDecl>(
D);
7120 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7121 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7128 BaseFD->addAttr(OMPDeclareVariantA);
7148 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7151 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7154 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7159 CE](StringRef ISATrait) {
7173 while (CalleeFnDecl) {
7174 for (OMPDeclareVariantAttr *A :
7176 Expr *VariantRef = A->getVariantFuncRef();
7178 VariantMatchInfo VMI;
7181 if (!isVariantApplicableInContext(VMI, OMPCtx,
7185 VMIs.push_back(VMI);
7186 Exprs.push_back(VariantRef);
7194 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7197 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7198 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7214 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7215 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7217 Context, MemberCall->getImplicitObjectArgument(),
7219 MemberCall->getValueKind(), MemberCall->getObjectKind());
7222 RParenLoc, ExecConfig);
7224 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7225 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7227 CalleeFnType, NewCalleeFnDecl->
getType(),
7238 VMIs.erase(VMIs.begin() + BestIdx);
7239 Exprs.erase(Exprs.begin() + BestIdx);
7240 }
while (!VMIs.empty());
7247std::optional<std::pair<FunctionDecl *, Expr *>>
7251 unsigned NumAppendArgs,
7254 if (!DG || DG.
get().isNull())
7255 return std::nullopt;
7257 const int VariantId = 1;
7259 if (!DG.
get().isSingleDecl()) {
7260 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7262 return std::nullopt;
7264 Decl *ADecl = DG.
get().getSingleDecl();
7265 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7266 ADecl = FTD->getTemplatedDecl();
7269 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7273 return std::nullopt;
7276 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7279 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7282 if (HasMultiVersionAttributes(FD)) {
7283 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7285 return std::nullopt;
7290 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7295 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7297 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7302 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7303 return std::nullopt;
7306 auto ShouldDelayChecks = [](
Expr *&
E,
bool) {
7312 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7314 return std::make_pair(FD, VariantRef);
7317 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&
E,
7318 bool IsScore) ->
bool {
7324 Diag(
E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7332 diag::err_omp_declare_variant_user_condition_not_constant)
7338 return std::nullopt;
7341 if (NumAppendArgs) {
7344 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7346 return std::nullopt;
7355 TD = dyn_cast_or_null<TypeDecl>(ND);
7358 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7359 return std::nullopt;
7364 if (PTy->isVariadic()) {
7365 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7366 return std::nullopt;
7369 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7370 Params.insert(Params.end(), NumAppendArgs, InteropType);
7371 AdjustedFnType = Context.
getFunctionType(PTy->getReturnType(), Params,
7372 PTy->getExtProtoInfo());
7380 auto *
Method = dyn_cast<CXXMethodDecl>(FD);
7383 AdjustedFnType, std::nullopt,
Method->getParent());
7395 return std::nullopt;
7397 VariantRef = ER.
get();
7405 false, Sema::AllowedExplicit::None,
7411 diag::err_omp_declare_variant_incompat_types)
7415 return std::nullopt;
7421 return std::nullopt;
7425 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7426 if (
auto *UO = dyn_cast<UnaryOperator>(
7428 VariantRefCast = UO->getSubExpr();
7437 return std::nullopt;
7445 return std::nullopt;
7447 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7451 return std::nullopt;
7456 diag::err_omp_declare_variant_same_base_function)
7458 return std::nullopt;
7467 diag::err_omp_declare_variant_incompat_types)
7468 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7470 return std::nullopt;
7475 else if (NewFD->getType()->isFunctionNoProtoType())
7481 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7483 diag::warn_omp_declare_variant_marked_as_declare_variant)
7486 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7487 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7488 return std::nullopt;
7491 enum DoesntSupport {
7500 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7501 if (CXXFD->isVirtual()) {
7504 return std::nullopt;
7507 if (isa<CXXConstructorDecl>(FD)) {
7510 return std::nullopt;
7513 if (isa<CXXDestructorDecl>(FD)) {
7516 return std::nullopt;
7520 if (FD->isDeleted()) {
7523 return std::nullopt;
7526 if (FD->isDefaulted()) {
7529 return std::nullopt;
7532 if (FD->isConstexpr()) {
7534 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7535 return std::nullopt;
7545 SemaRef.
PDiag(diag::err_omp_declare_variant_doesnt_support)),
7551 return std::nullopt;
7552 return std::make_pair(FD, cast<Expr>(DRE));
7569 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7570 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7571 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7573 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7574 VariantMatchInfo VMI;
7576 if (!llvm::is_contained(
7577 VMI.ConstructTraits,
7578 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7579 if (!AllAdjustArgs.empty())
7580 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7582 if (!AppendArgs.empty())
7583 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7594 for (
Expr *
E : AllAdjustArgs) {
7596 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E)) {
7597 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7599 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7603 if (!AdjustVars.insert(CanonPVD).second) {
7604 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7613 Diag(
E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7622 for (
Expr *
E : AdjustArgsNeedDeviceAddr) {
7624 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E)) {
7625 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7628 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7634 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7636 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7637 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7638 AdjustArgsNeedDevicePtr.size(),
7639 const_cast<Expr **
>(AdjustArgsNeedDeviceAddr.data()),
7640 AdjustArgsNeedDeviceAddr.size(),
7641 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7647 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7648 assert(CS &&
"Captured statement expected");
7657 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7686struct LoopIterationSpace final {
7689 bool IsStrictCompare =
false;
7691 Expr *PreCond =
nullptr;
7694 Expr *NumIterations =
nullptr;
7696 Expr *CounterVar =
nullptr;
7698 Expr *PrivateCounterVar =
nullptr;
7700 Expr *CounterInit =
nullptr;
7703 Expr *CounterStep =
nullptr;
7705 bool Subtract =
false;
7715 Expr *MinValue =
nullptr;
7719 Expr *MaxValue =
nullptr;
7721 bool IsNonRectangularLB =
false;
7723 bool IsNonRectangularUB =
false;
7726 unsigned LoopDependentIdx = 0;
7730 Expr *FinalCondition =
nullptr;
7737 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7738 VarDecl *ForbiddenVar =
nullptr;
7742 explicit ForSubExprChecker(
7743 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7744 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7747 ShouldVisitImplicitCode =
true;
7752 if (!isa<VarDecl, BindingDecl>(VD))
7755 if (
V->getType()->isReferenceType()) {
7765 Decl *Canon =
V->getCanonicalDecl();
7766 if (CollapsedLoopVarDecls.contains(Canon)) {
7775 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
7776 SourceRange getErrRange()
const {
return ErrLoc; }
7782class OpenMPIterationSpaceChecker {
7786 bool SupportsNonRectangular;
7794 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7804 Expr *LCRef =
nullptr;
7810 Expr *Step =
nullptr;
7817 std::optional<bool> TestIsLessOp;
7819 bool TestIsStrictOp =
false;
7821 bool SubtractStep =
false;
7826 std::optional<unsigned> InitDependOnLC;
7829 std::optional<unsigned> CondDependOnLC;
7831 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
7832 bool IsInitializer);
7838 OpenMPIterationSpaceChecker(
7839 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
7841 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7842 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7843 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7844 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7847 bool checkAndSetInit(
Stmt *S,
bool EmitDiags =
true);
7850 bool checkAndSetCond(
Expr *S);
7853 bool checkAndSetInc(
Expr *S);
7855 ValueDecl *getLoopDecl()
const {
return LCDecl; }
7857 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
7859 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
7861 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
7863 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
7865 bool shouldSubtractStep()
const {
return SubtractStep; }
7867 bool isStrictTestOp()
const {
return TestIsStrictOp; }
7869 Expr *buildNumIterations(
7871 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7875 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7878 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7879 DSAStackTy &DSA)
const;
7882 Expr *buildPrivateCounterVar()
const;
7886 Expr *buildCounterStep()
const;
7890 buildOrderedLoopData(
Scope *S,
Expr *Counter,
7891 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7895 std::pair<Expr *, Expr *> buildMinMaxValues(
7896 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7898 Expr *buildFinalCondition(
Scope *S)
const;
7900 bool dependent()
const;
7902 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
7904 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
7906 unsigned getLoopDependentIdx()
const {
7907 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7913 bool checkAndSetIncRHS(
Expr *RHS);
7918 bool setUB(
Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
7921 bool setStep(
Expr *NewStep,
bool Subtract);
7924bool OpenMPIterationSpaceChecker::dependent()
const {
7926 assert(!LB && !UB && !Step);
7934bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
7936 Expr *NewLB,
bool EmitDiags) {
7938 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
7939 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7943 LCRef = NewLCRefExpr;
7944 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7946 if ((Ctor->isCopyOrMoveConstructor() ||
7947 Ctor->isConvertingConstructor(
false)) &&
7948 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
7952 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
7956bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
7960 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
7961 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7966 TestIsLessOp = LessOp;
7967 TestIsStrictOp = StrictOp;
7968 ConditionSrcRange = SR;
7970 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
7974bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
7976 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
7986 NewStep = Val.
get();
7999 std::optional<llvm::APSInt>
Result =
8010 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8011 if (UB && (IsConstZero ||
8012 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8013 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8015 diag::err_omp_loop_incr_not_compatible)
8017 SemaRef.
Diag(ConditionLoc,
8018 diag::note_omp_loop_cond_requires_compatible_incr)
8019 << *TestIsLessOp << ConditionSrcRange;
8022 if (*TestIsLessOp == Subtract) {
8026 Subtract = !Subtract;
8031 SubtractStep = Subtract;
8038class LoopCounterRefChecker final
8045 bool IsInitializer =
true;
8046 bool SupportsNonRectangular;
8047 unsigned BaseLoopId = 0;
8050 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8051 << (IsInitializer ? 0 : 1);
8054 const auto &&
Data = Stack.isLoopControlVariable(VD);
8060 llvm::raw_svector_ostream OS(Name);
8064 diag::err_omp_wrong_dependency_iterator_type)
8066 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
8069 if (
Data.first && !SupportsNonRectangular) {
8070 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_invariant_dependency);
8074 (DepDecl || (PrevDepDecl &&
8076 if (!DepDecl && PrevDepDecl)
8077 DepDecl = PrevDepDecl;
8079 llvm::raw_svector_ostream OS(Name);
8083 diag::err_omp_invariant_or_linear_dependency)
8089 BaseLoopId =
Data.first;
8097 if (isa<VarDecl>(VD))
8098 return checkDecl(
E, VD);
8104 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8105 return checkDecl(
E, VD);
8109 bool VisitStmt(
const Stmt *S) {
8111 for (
const Stmt *Child : S->children())
8112 Res = (Child && Visit(Child)) || Res;
8115 explicit LoopCounterRefChecker(
Sema &SemaRef, DSAStackTy &Stack,
8116 const ValueDecl *CurLCDecl,
bool IsInitializer,
8118 bool SupportsNonRectangular =
true)
8119 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8120 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8121 SupportsNonRectangular(SupportsNonRectangular) {}
8122 unsigned getBaseLoopId()
const {
8123 assert(CurLCDecl &&
"Expected loop dependency.");
8127 assert(CurLCDecl &&
"Expected loop dependency.");
8133std::optional<unsigned>
8134OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8135 bool IsInitializer) {
8137 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8138 DepDecl, SupportsNonRectangular);
8139 if (LoopStmtChecker.Visit(S)) {
8140 DepDecl = LoopStmtChecker.getDepDecl();
8141 return LoopStmtChecker.getBaseLoopId();
8143 return std::nullopt;
8146bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8157 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8161 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8162 if (!ExprTemp->cleanupsHaveSideEffects())
8163 S = ExprTemp->getSubExpr();
8165 if (!CollapsedLoopVarDecls.empty()) {
8166 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8167 if (!FSEC.TraverseStmt(S)) {
8169 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8175 InitSrcRange = S->getSourceRange();
8176 if (
Expr *
E = dyn_cast<Expr>(S))
8178 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8179 if (BO->getOpcode() == BO_Assign) {
8181 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8182 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8184 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8186 return setLCDeclAndLB(DRE->
getDecl(), DRE, BO->getRHS(), EmitDiags);
8188 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8189 if (ME->isArrow() &&
8190 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8191 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8195 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8196 if (DS->isSingleDecl()) {
8197 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8198 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8201 SemaRef.Diag(S->getBeginLoc(),
8202 diag::ext_omp_loop_not_canonical_init)
8203 << S->getSourceRange();
8204 return setLCDeclAndLB(
8207 Var->getType().getNonReferenceType(),
8209 Var->getInit(), EmitDiags);
8213 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8214 if (CE->getOperator() == OO_Equal) {
8215 Expr *LHS = CE->getArg(0);
8216 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8217 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
8219 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8221 return setLCDeclAndLB(DRE->
getDecl(), DRE, CE->getArg(1), EmitDiags);
8223 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8224 if (ME->isArrow() &&
8225 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8226 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8232 if (dependent() || SemaRef.CurContext->isDependentContext())
8235 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8236 << S->getSourceRange();
8247 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(
E))
8249 if ((Ctor->isCopyOrMoveConstructor() ||
8250 Ctor->isConvertingConstructor(
false)) &&
8251 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8253 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(
E)) {
8254 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
8257 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(
E))
8258 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8263bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8270 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8272 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8273 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8279 if (!CollapsedLoopVarDecls.empty()) {
8280 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8281 if (!FSEC.TraverseStmt(S)) {
8283 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8290 auto &&CheckAndSetCond =
8295 if (getInitLCDecl(LHS) == LCDecl)
8296 return setUB(
const_cast<Expr *
>(RHS),
8298 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8299 if (getInitLCDecl(RHS) == LCDecl)
8300 return setUB(
const_cast<Expr *
>(LHS),
8302 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8303 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8304 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8308 return std::nullopt;
8310 std::optional<bool> Res;
8311 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8314 RBO->getOperatorLoc());
8315 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8316 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8317 BO->getSourceRange(), BO->getOperatorLoc());
8318 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8319 if (CE->getNumArgs() == 2) {
8320 Res = CheckAndSetCond(
8322 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8327 if (dependent() || SemaRef.CurContext->isDependentContext())
8329 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8330 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8334bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8341 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8342 if (BO->isAdditiveOp()) {
8343 bool IsAdd = BO->getOpcode() == BO_Add;
8344 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8345 return setStep(BO->getRHS(), !IsAdd);
8346 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8347 return setStep(BO->getLHS(),
false);
8349 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8350 bool IsAdd = CE->getOperator() == OO_Plus;
8351 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8352 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8353 return setStep(CE->getArg(1), !IsAdd);
8354 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8355 return setStep(CE->getArg(0),
false);
8358 if (dependent() || SemaRef.CurContext->isDependentContext())
8360 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8365bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8380 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8383 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8384 if (!ExprTemp->cleanupsHaveSideEffects())
8385 S = ExprTemp->getSubExpr();
8387 if (!CollapsedLoopVarDecls.empty()) {
8388 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8389 if (!FSEC.TraverseStmt(S)) {
8391 SemaRef.Diag(
Range.
getBegin(), diag::err_omp_loop_bad_collapse_var)
8397 IncrementSrcRange = S->getSourceRange();
8398 S = S->IgnoreParens();
8399 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8400 if (UO->isIncrementDecrementOp() &&
8401 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8402 return setStep(SemaRef
8403 .ActOnIntegerConstant(UO->getBeginLoc(),
8404 (UO->isDecrementOp() ? -1 : 1))
8407 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8408 switch (BO->getOpcode()) {
8411 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8412 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8415 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8416 return checkAndSetIncRHS(BO->getRHS());
8421 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8422 switch (CE->getOperator()) {
8425 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8426 return setStep(SemaRef
8427 .ActOnIntegerConstant(
8429 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8435 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8436 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8439 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8440 return checkAndSetIncRHS(CE->getArg(1));
8446 if (dependent() || SemaRef.CurContext->isDependentContext())
8448 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8449 << S->getSourceRange() << LCDecl;
8455 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8456 StringRef Name =
".capture_expr.") {
8464 auto I = Captures.find(
Capture);
8465 if (I != Captures.end())
8478 bool TestIsStrictOp,
bool RoundToStep,
8479 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8480 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8483 llvm::APSInt LRes, SRes;
8484 bool IsLowerConst =
false, IsStepConst =
false;
8485 if (std::optional<llvm::APSInt> Res =
8488 IsLowerConst =
true;
8490 if (std::optional<llvm::APSInt> Res =
8495 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8496 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8497 (TestIsStrictOp && LRes.isStrictlyPositive()));
8498 bool NeedToReorganize =
false;
8500 if (!NoNeedToConvert && IsLowerConst &&
8501 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8502 NoNeedToConvert =
true;
8504 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8505 ? LRes.getBitWidth()
8506 : SRes.getBitWidth();
8507 LRes = LRes.extend(BW + 1);
8508 LRes.setIsSigned(
true);
8509 SRes = SRes.extend(BW + 1);
8510 SRes.setIsSigned(
true);
8512 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8513 LRes = LRes.trunc(BW);
8515 if (TestIsStrictOp) {
8516 unsigned BW = LRes.getBitWidth();
8517 LRes = LRes.extend(BW + 1);
8518 LRes.setIsSigned(
true);
8521 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8523 LRes = LRes.trunc(BW);
8525 NeedToReorganize = NoNeedToConvert;
8528 bool IsUpperConst =
false;
8529 if (std::optional<llvm::APSInt> Res =
8532 IsUpperConst =
true;
8534 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8535 (!RoundToStep || IsStepConst)) {
8536 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8537 : URes.getBitWidth();
8538 LRes = LRes.extend(BW + 1);
8539 LRes.setIsSigned(
true);
8540 URes = URes.extend(BW + 1);
8541 URes.setIsSigned(
true);
8543 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8544 NeedToReorganize = NoNeedToConvert;
8549 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8555 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8558 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8569 if (!Lower || !Upper || NewStep.
isInvalid())
8575 if (NeedToReorganize) {
8589 S, DefaultLoc, BO_Add, Diff.
get(),
8599 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8603 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8619 S, DefaultLoc, BO_Sub, Diff.
get(),
8639 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8647Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8649 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8658 if (InitDependOnLC) {
8659 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8660 if (!IS.MinValue || !IS.MaxValue)
8669 IS.CounterVar, MinValue.
get());
8674 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8689 IS.CounterVar, MaxValue.
get());
8694 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8703 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8705 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8706 if (!LBMin || !LBMax)
8710 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8714 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8718 if (*TestIsLessOp) {
8722 MinLessMax, LBMin, LBMax);
8725 LBVal = MinLB.
get();
8730 MinLessMax, LBMax, LBMin);
8733 LBVal = MaxLB.
get();
8737 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8740 LBVal = LBMinVal.
get();
8744 if (CondDependOnLC) {
8745 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8746 if (!IS.MinValue || !IS.MaxValue)
8755 IS.CounterVar, MinValue.
get());
8760 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8775 IS.CounterVar, MaxValue.
get());
8780 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
8789 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
8791 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
8792 if (!UBMin || !UBMax)
8796 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8799 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
8800 Captures,
".min_greater_max")
8804 if (*TestIsLessOp) {
8808 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8811 UBVal = MaxUB.
get();
8816 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8819 UBVal = MinUB.
get();
8822 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8823 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8824 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
8825 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
8826 if (!Upper || !Lower)
8829 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8830 Step, VarType, TestIsStrictOp,
8839 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
8842 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
8845 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
8855 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
8856 if (NewSize !=
C.getTypeSize(
Type)) {
8857 if (NewSize <
C.getTypeSize(
Type)) {
8858 assert(NewSize == 64 &&
"incorrect loop var size");
8859 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8860 << InitSrcRange << ConditionSrcRange;
8862 QualType NewType =
C.getIntTypeForBitwidth(
8864 C.getTypeSize(
Type) < NewSize);
8878std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8879 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8883 return std::make_pair(
nullptr,
nullptr);
8886 Expr *MinExpr =
nullptr;
8887 Expr *MaxExpr =
nullptr;
8888 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8889 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8891 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8893 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8895 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8897 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8898 if (!Upper || !Lower)
8899 return std::make_pair(
nullptr,
nullptr);
8909 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8910 Step, VarType, TestIsStrictOp,
8913 return std::make_pair(
nullptr,
nullptr);
8919 return std::make_pair(
nullptr,
nullptr);
8921 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8923 return std::make_pair(
nullptr,
nullptr);
8924 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
8926 return std::make_pair(
nullptr,
nullptr);
8931 return std::make_pair(
nullptr,
nullptr);
8943 return std::make_pair(
nullptr,
nullptr);
8945 if (*TestIsLessOp) {
8949 S, DefaultLoc, BO_Add,
8953 return std::make_pair(
nullptr,
nullptr);
8958 S, DefaultLoc, BO_Sub,
8962 return std::make_pair(
nullptr,
nullptr);
8971 return std::make_pair(
nullptr,
nullptr);
8976 return std::make_pair(
nullptr,
nullptr);
8979 MaxExpr = Diff.
get();
8981 MinExpr = Diff.
get();
8983 return std::make_pair(MinExpr, MaxExpr);
8986Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
8987 if (InitDependOnLC || CondDependOnLC)
8992Expr *OpenMPIterationSpaceChecker::buildPreCond(
8994 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8999 if (CondDependOnLC || InitDependOnLC)
9010 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9011 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9017 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9018 : (TestIsStrictOp ? BO_GT : BO_GE),
9019 NewLB.
get(), NewUB.
get());
9030 return CondExpr.
isUsable() ? CondExpr.
get() : Cond;
9034DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9035 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9036 DSAStackTy &DSA)
const {
9037 auto *VD = dyn_cast<VarDecl>(LCDecl);
9042 const DSAStackTy::DSAVarData
Data =
9043 DSA.getTopDSA(LCDecl,
false);
9047 Captures.insert(std::make_pair(LCRef, Ref));
9050 return cast<DeclRefExpr>(LCRef);
9053Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
9059 isa<VarDecl>(LCDecl)
9070Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
9073Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
9075Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9083 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9084 "Expected only + or - operations for depend clauses.");
9096 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9098 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9099 if (!Upper || !Lower)
9103 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9104 false,
false, Captures);
9114 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
9115 assert(
Init &&
"Expected loop in canonical form.");
9116 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9123 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9125 if (!ISC.checkAndSetInit(
Init,
false)) {
9127 auto *VD = dyn_cast<VarDecl>(
D);
9135 VD = cast<VarDecl>(PrivateRef->
getDecl());
9138 DSAStack->addLoopControlVariable(
D, VD);
9141 DSAStack->resetPossibleLoopCounter();
9142 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9155 DSAStackTy::DSAVarData DVar =
9159 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9162 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9165 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9168 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9170 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9172 IsOpenMPTaskloopDirective(DKind) ||
9175 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9176 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9178 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9180 << getOpenMPDirectiveName(DKind, OMPVersion)
9182 if (DVar.RefExpr ==
nullptr)
9183 DVar.CKind = PredeterminedCKind;
9185 }
else if (LoopDeclRefExpr) {
9190 if (DVar.CKind == OMPC_unknown)
9191 DSAStack->addDSA(
D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9195 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9200class OMPDoacrossKind {
9203 return C->getDependenceType() == OMPC_DOACROSS_source ||
9204 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9207 return C->getDependenceType() == OMPC_DOACROSS_sink;
9210 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9218 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9219 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9220 Expr *OrderedLoopCountExpr,
9223 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9224 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9229 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9230 S = CanonLoop->getLoopStmt();
9231 auto *For = dyn_cast_or_null<ForStmt>(S);
9232 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9234 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9235 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
9236 SemaRef.
Diag(S->getBeginLoc(), diag::err_omp_not_for)
9237 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9238 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9239 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9240 if (TotalNestedLoopCount > 1) {
9241 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9242 SemaRef.
Diag(DSA.getConstructLoc(),
9243 diag::note_omp_collapse_ordered_expr)
9246 else if (CollapseLoopCountExpr)
9248 diag::note_omp_collapse_ordered_expr)
9250 else if (OrderedLoopCountExpr)
9252 diag::note_omp_collapse_ordered_expr)
9257 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9263 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9264 For ? For->getForLoc() : CXXFor->getForLoc(),
9265 CollapsedLoopVarDecls);
9268 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9269 if (ISC.checkAndSetInit(
Init))
9272 bool HasErrors =
false;
9275 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9285 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9299 VarsWithImplicitDSA.erase(LCDecl);
9304 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9307 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9314 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9315 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9316 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9317 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9324 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9325 ISC.buildCounterVar(Captures, DSA);
9326 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9327 ISC.buildPrivateCounterVar();
9328 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9329 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9330 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9331 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9332 ISC.getConditionSrcRange();
9333 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9334 ISC.getIncrementSrcRange();
9335 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9336 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9337 ISC.isStrictTestOp();
9338 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9339 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9340 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9341 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9342 ISC.buildFinalCondition(DSA.getCurScope());
9343 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9344 ISC.doesInitDependOnLC();
9345 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9346 ISC.doesCondDependOnLC();
9347 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9348 ISC.getLoopDependentIdx();
9351 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9352 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9353 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9354 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9355 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9356 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9357 if (!HasErrors && DSA.isOrderedRegion()) {
9358 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9359 if (CurrentNestedLoopCount <
9360 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9361 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9362 CurrentNestedLoopCount,
9363 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9364 DSA.getOrderedRegionParam().second->setLoopCounter(
9365 CurrentNestedLoopCount,
9366 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9369 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9370 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9371 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9373 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9374 if (CurrentNestedLoopCount >= NumLoops) {
9378 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9379 Pair.second.size() <= CurrentNestedLoopCount) {
9381 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9384 OMPDoacrossKind ODK;
9385 if (DoacrossC && ODK.isSink(DoacrossC) &&
9386 Pair.second.size() <= CurrentNestedLoopCount) {
9388 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9393 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9394 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9395 (DoacrossC && ODK.isSource(DoacrossC)))
9396 CntValue = ISC.buildOrderedLoopData(
9398 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9400 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9403 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9411 CntValue = ISC.buildOrderedLoopData(
9413 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9414 DepLoc, Inc, clang::OO_Minus);
9416 CntValue = ISC.buildOrderedLoopData(
9418 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9419 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9420 Pair.second[CurrentNestedLoopCount].second);
9422 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9424 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9435 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9439 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9460 bool IsNonRectangularLB,
9461 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9470 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9485 if (Captures && !IsNonRectangularLB)
9486 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9495 Update.get()->getType()->isOverloadableType()) {
9502 SemaRef.
BuildBinOp(S,
Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9503 VarRef.
get(), SavedUpdate.
get());
9514 NewStart.
get(), SavedUpdate.
get());
9539 unsigned HasBits =
C.getTypeSize(OldType);
9540 if (HasBits >= Bits)
9543 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9553 if (std::optional<llvm::APSInt>
Result =
9562 if (!PreInits.empty()) {
9583 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9592 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9593 if (!Captures.empty()) {
9595 for (
const auto &Pair : Captures)
9596 PreInits.push_back(Pair.second->getDecl());
9604 if (PreInits.empty())
9608 for (
Stmt *S : PreInits)
9615 Expr *PostUpdate =
nullptr;
9616 if (!PostUpdates.empty()) {
9617 for (
Expr *
E : PostUpdates) {
9623 PostUpdate = PostUpdate
9637 int NestingDepth = 0;
9638 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9660 if (NestingDepth > 0)
9671 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9678 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->
containsErrors()) ||
9679 (OrderedLoopCountExpr && OrderedLoopCountExpr->
containsErrors()))
9682 unsigned NestedLoopCount = 1;
9683 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9687 if (CollapseLoopCountExpr) {
9692 NestedLoopCount =
Result.Val.getInt().getLimitedValue();
9695 FVDF.TraverseStmt(AStmt);
9701 unsigned OrderedLoopCount = 1;
9702 if (OrderedLoopCountExpr) {
9709 if (
Result.getLimitedValue() < NestedLoopCount) {
9711 diag::err_omp_wrong_ordered_loop_count)
9714 diag::note_collapse_loop_count)
9717 OrderedLoopCount =
Result.getLimitedValue();
9725 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9726 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9730 SupportsNonPerfectlyNested, NumLoops,
9731 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9732 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9733 &IterSpaces, &Captures,
9734 &CollapsedLoopVarDecls](
unsigned Cnt,
Stmt *CurStmt) {
9736 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9737 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9738 VarsWithImplicitDSA, IterSpaces, Captures,
9739 CollapsedLoopVarDecls))
9741 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9742 IterSpaces[Cnt].CounterVar) {
9744 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9745 if (isa<OMPCapturedExprDecl>(DRE->
getDecl())) {
9746 Captures[DRE] = DRE;
9752 Stmt *DependentPreInits = Transform->getPreInits();
9753 if (!DependentPreInits)
9760 for (
Stmt *S : Constituents) {
9761 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9762 for (
Decl *
C : DC->decls()) {
9763 auto *
D = cast<VarDecl>(
C);
9765 SemaRef,
D,
D->getType().getNonReferenceType(),
9767 Captures[Ref] = Ref;
9774 Built.
clear(NestedLoopCount);
9777 return NestedLoopCount;
9810 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
9811 Expr *N0 = IterSpaces[0].NumIterations;
9830 return NestedLoopCount;
9833 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
9835 Scope *CurScope = DSA.getCurScope();
9836 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9837 if (PreCond.isUsable()) {
9839 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9840 PreCond.get(), IterSpaces[Cnt].PreCond);
9842 Expr *N = IterSpaces[Cnt].NumIterations;
9844 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
9847 CurScope,
Loc, BO_Mul, LastIteration32.
get(),
9855 CurScope,
Loc, BO_Mul, LastIteration64.
get(),
9865 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
9867 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
9868 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9872 LastIteration64.
get(), SemaRef))))
9873 LastIteration = LastIteration32;
9892 LastIteration.
get(),
9904 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
9905 LastIteration = SaveRef;
9918 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9947 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
9956 UB.
get(), LastIteration.
get());
9959 LastIteration.
get(), UB.
get());
9960 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
9985 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
9988 LastIteration.
get(), CombUB.
get());
9989 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
9994 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9998 "Unexpected number of parameters in loop combined directive");
10039 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
10045 bool UseStrictCompare =
10047 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
10048 return LIS.IsStrictCompare;
10054 if (UseStrictCompare) {
10057 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10069 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
10072 NumIterations.
get());
10075 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
10076 NumIterations.
get());
10081 Expr *BoundCombUB = CombUB.
get();
10082 if (UseStrictCompare) {
10086 CurScope, CondLoc, BO_Add, BoundCombUB,
10094 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10095 IV.
get(), BoundCombUB);
10102 if (!Inc.isUsable())
10104 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
10106 if (!Inc.isUsable())
10113 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10119 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
10130 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
10146 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
10158 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10172 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10175 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10176 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10180 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10181 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10185 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10196 DistEUBLoc, NewPrevUB.
get());
10201 UB.
get(), NewPrevUB.
get());
10203 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10204 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10212 Expr *BoundPrevUB = PrevUB.
get();
10213 if (UseStrictCompare) {
10217 CurScope, CondLoc, BO_Add, BoundPrevUB,
10225 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10226 IV.
get(), BoundPrevUB);
10230 bool HasErrors =
false;
10231 Built.
Counters.resize(NestedLoopCount);
10232 Built.
Inits.resize(NestedLoopCount);
10233 Built.
Updates.resize(NestedLoopCount);
10234 Built.
Finals.resize(NestedLoopCount);
10255 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10256 LoopIterationSpace &IS = IterSpaces[Cnt];
10262 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10263 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10264 IterSpaces[K].NumIterations);
10269 if (Cnt + 1 < NestedLoopCount)
10274 if (!
Iter.isUsable()) {
10283 if (Cnt + 1 < NestedLoopCount)
10288 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10291 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10293 SemaRef, VD, IS.CounterVar->
getType(), IS.CounterVar->getExprLoc(),
10297 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10298 if (!
Init.isUsable()) {
10303 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
Iter,
10304 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10305 if (!
Update.isUsable()) {
10313 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10314 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10315 if (!Final.isUsable()) {
10320 if (!
Update.isUsable() || !Final.isUsable()) {
10325 Built.
Counters[Cnt] = IS.CounterVar;
10329 Built.
Finals[Cnt] = Final.get();
10333 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10352 Built.
PreCond = PreCond.get();
10356 Built.
Inc = Inc.get();
10357 Built.
LB = LB.
get();
10358 Built.
UB = UB.
get();
10359 Built.
IL = IL.
get();
10360 Built.
ST = ST.
get();
10362 Built.
NLB = NextLB.
get();
10363 Built.
NUB = NextUB.
get();
10378 return NestedLoopCount;
10382 auto CollapseClauses =
10383 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10384 if (CollapseClauses.begin() != CollapseClauses.end())
10385 return (*CollapseClauses.begin())->getNumForLoops();
10390 auto OrderedClauses =
10391 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10392 if (OrderedClauses.begin() != OrderedClauses.end())
10393 return (*OrderedClauses.begin())->getNumForLoops();
10402 for (
const OMPClause *Clause : Clauses) {
10404 Safelen = cast<OMPSafelenClause>(Clause);
10406 Simdlen = cast<OMPSimdlenClause>(Clause);
10407 if (Safelen && Simdlen)
10411 if (Simdlen && Safelen) {
10425 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10426 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10431 if (SimdlenRes > SafelenRes) {
10433 diag::err_omp_wrong_simdlen_safelen_values)
10449 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10456 if (NestedLoopCount == 0)
10466 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10467 return SimdDirective;
10476 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10483 if (NestedLoopCount == 0)
10490 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10492 return ForDirective;
10503 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10507 unsigned NestedLoopCount =
10510 VarsWithImplicitDSA, B);
10511 if (NestedLoopCount == 0)
10521 NestedLoopCount, Clauses, AStmt, B);
10525 Stmt *AStmt, DSAStackTy *Stack) {
10529 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10530 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
10531 auto BaseStmt = AStmt;
10532 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10534 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10535 auto S =
C->children();
10536 if (S.begin() == S.end())
10540 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10541 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10543 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10544 diag::err_omp_sections_substmt_not_section)
10545 << getOpenMPDirectiveName(DKind, OMPVersion);
10548 cast<OMPSectionDirective>(SectionStmt)
10549 ->setHasCancel(Stack->isCancelRegion());
10552 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10553 << getOpenMPDirectiveName(DKind, OMPVersion);
10588 if (
auto *CE = dyn_cast<CallExpr>(
E))
10589 if (CE->getDirectCallee())
10601 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10611 Expr *TargetCall =
nullptr;
10613 auto *
E = dyn_cast<Expr>(S);
10615 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10621 if (
auto *BO = dyn_cast<BinaryOperator>(
E)) {
10622 if (BO->getOpcode() == BO_Assign)
10625 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(
E))
10626 if (COCE->getOperator() == OO_Equal)
10641 Clauses, AStmt, TargetCallLoc);
10646 DSAStackTy *Stack) {
10647 bool ErrorFound =
false;
10649 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10650 for (
Expr *RefExpr : LPC->varlist()) {
10653 Expr *SimpleRefExpr = RefExpr;
10656 auto &&Info = Stack->isLoopControlVariable(
D);
10659 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10660 << getOpenMPDirectiveName(K, OMPVersion);
10689 if (NestedLoopCount == 0)
10693 "omp loop exprs were not built");
10696 NestedLoopCount, Clauses, AStmt, B);
10715 unsigned NestedLoopCount =
10718 VarsWithImplicitDSA, B);
10719 if (NestedLoopCount == 0)
10723 "omp loop exprs were not built");
10725 DSAStack->setParentTeamsRegionLoc(StartLoc);
10728 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10749 unsigned NestedLoopCount =
10752 VarsWithImplicitDSA, B);
10753 if (NestedLoopCount == 0)
10757 "omp loop exprs were not built");
10760 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10782 unsigned NestedLoopCount =
10785 VarsWithImplicitDSA, B);
10786 if (NestedLoopCount == 0)
10790 "omp loop exprs were not built");
10793 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10814 unsigned NestedLoopCount =
10817 VarsWithImplicitDSA, B);
10818 if (NestedLoopCount == 0)
10822 "omp loop exprs were not built");
10825 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10835 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10842 const OMPClause *Copyprivate =
nullptr;
10843 for (
const OMPClause *Clause : Clauses) {
10847 Copyprivate = Clause;
10848 if (Copyprivate && Nowait) {
10850 diag::err_omp_single_copyprivate_with_nowait);
10890 bool ErrorFound =
false;
10893 bool DependentHint =
false;
10895 if (
C->getClauseKind() == OMPC_hint) {
10897 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10900 Expr *
E = cast<OMPHintClause>(
C)->getHint();
10903 DependentHint =
true;
10906 HintLoc =
C->getBeginLoc();
10912 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
10913 if (Pair.first && DirName.
getName() && !DependentHint) {
10914 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10915 Diag(StartLoc, diag::err_omp_critical_with_hint);
10917 Diag(HintLoc, diag::note_omp_critical_hint_here)
10918 << 0 <<
toString(Hint, 10,
false);
10920 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10921 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
10922 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
10927 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10935 EndLoc, Clauses, AStmt);
10936 if (!Pair.first && DirName.
getName() && !DependentHint)
10937 DSAStack->addCriticalWithHint(Dir, Hint);
10952 unsigned NestedLoopCount =
10955 VarsWithImplicitDSA, B);
10956 if (NestedLoopCount == 0)
10963 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10979 unsigned NestedLoopCount =
10982 VarsWithImplicitDSA, B);
10983 if (NestedLoopCount == 0)
10993 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11006 DSAStack->getTaskgroupReductionRef());
11019 DSAStack->getTaskgroupReductionRef());
11040 bool ErrorFound =
false;
11042 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
11046 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11069 {OMPC_detach, OMPC_mergeable}))
11075 AStmt,
DSAStack->isCancelRegion());
11091 bool InExContext) {
11093 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11095 if (AtC && !InExContext && AtC->
getAtKind() == OMPC_AT_execution) {
11100 if (!AtC || AtC->
getAtKind() == OMPC_AT_compilation) {
11102 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11104 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11105 std::optional<std::string> SL =
11108 if (MessageC && !SL)
11110 diag::warn_clause_expected_string)
11112 if (SeverityC && SeverityC->
getSeverityKind() == OMPC_SEVERITY_warning)
11114 << SL.value_or(
"WARNING");
11116 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or(
"ERROR");
11117 if (!SeverityC || SeverityC->
getSeverityKind() != OMPC_SEVERITY_warning)
11129 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11131 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11133 if (NowaitC && !HasDependC) {
11134 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11149 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
11155 DSAStack->getTaskgroupReductionRef());
11164 if (
C->getClauseKind() == OMPC_flush)
11165 FC = cast<OMPFlushClause>(
C);
11173 if (
C->getClauseKind() == OMPC_acq_rel ||
11174 C->getClauseKind() == OMPC_acquire ||
11175 C->getClauseKind() == OMPC_release ||
11176 C->getClauseKind() == OMPC_seq_cst ) {
11177 if (MemOrderKind != OMPC_unknown) {
11178 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11179 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11181 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11184 MemOrderKind =
C->getClauseKind();
11185 MemOrderLoc =
C->getBeginLoc();
11189 if (FC && OrderClause) {
11192 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11202 if (Clauses.empty()) {
11203 Diag(StartLoc, diag::err_omp_depobj_expected);
11205 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11206 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11210 if (Clauses.size() > 2) {
11211 Diag(Clauses[2]->getBeginLoc(),
11212 diag::err_omp_depobj_single_clause_expected);
11214 }
else if (Clauses.size() < 1) {
11215 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11225 if (Clauses.size() != 1) {
11226 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11227 diag::err_omp_scan_single_clause_expected);
11232 Scope *ParentS = S->getParent();
11236 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11237 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11242 if (
DSAStack->doesParentHasScanDirective()) {
11243 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11245 diag::note_omp_previous_directive)
11249 DSAStack->setParentHasScanDirective(StartLoc);
11257 const OMPClause *DependFound =
nullptr;
11258 const OMPClause *DependSourceClause =
nullptr;
11259 const OMPClause *DependSinkClause =
nullptr;
11260 const OMPClause *DoacrossFound =
nullptr;
11261 const OMPClause *DoacrossSourceClause =
nullptr;
11262 const OMPClause *DoacrossSinkClause =
nullptr;
11263 bool ErrorFound =
false;
11267 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11268 auto DC = dyn_cast<OMPDependClause>(
C);
11270 DependFound = DC ?
C :
nullptr;
11271 DoacrossFound = DOC ?
C :
nullptr;
11272 OMPDoacrossKind ODK;
11273 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11274 (DOC && (ODK.isSource(DOC)))) {
11275 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11277 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11278 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11284 DependSourceClause =
C;
11286 DoacrossSourceClause =
C;
11288 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11289 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11290 << (DC ?
"depend" :
"doacross") << 0;
11293 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11294 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11295 if (DependSourceClause || DoacrossSourceClause) {
11296 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11297 << (DC ?
"depend" :
"doacross") << 1;
11301 DependSinkClause =
C;
11303 DoacrossSinkClause =
C;
11305 }
else if (
C->getClauseKind() == OMPC_threads) {
11306 TC = cast<OMPThreadsClause>(
C);
11307 }
else if (
C->getClauseKind() == OMPC_simd) {
11308 SC = cast<OMPSIMDClause>(
C);
11311 if (!ErrorFound && !SC &&
11316 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11319 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11322 Diag(
Loc, diag::err_omp_depend_clause_thread_simd)
11327 }
else if ((DependFound || DoacrossFound) &&
11328 !
DSAStack->getParentOrderedRegionParam().first) {
11331 Diag(
Loc, diag::err_omp_ordered_directive_without_param)
11335 }
else if (TC || Clauses.empty()) {
11336 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11338 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11339 << (TC !=
nullptr);
11344 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11352 if (!DependFound && !DoacrossFound) {
11353 if (
DSAStack->doesParentHasOrderedDirective()) {
11354 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11356 diag::note_omp_previous_directive)
11360 DSAStack->setParentHasOrderedDirective(StartLoc);
11364 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
11376class OpenMPAtomicUpdateChecker {
11378 enum ExprAnalysisErrorCode {
11382 NotABinaryOrUnaryExpression,
11384 NotAnUnaryIncDecExpression,
11390 NotABinaryExpression,
11393 NotABinaryOperator,
11396 NotAnUpdateExpression,
11399 NotAValidExpression,
11417 bool IsXLHSInRHSPart;
11422 bool IsPostfixUpdate;
11425 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11426 : SemaRef(SemaRef),
X(nullptr),
E(nullptr), UpdateExpr(nullptr),
11427 IsXLHSInRHSPart(
false), Op(BO_PtrMemD), IsPostfixUpdate(
false) {}
11435 bool checkStatement(
Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11437 Expr *getX()
const {
return X; }
11439 Expr *getExpr()
const {
return E; }
11443 Expr *getUpdateExpr()
const {
return UpdateExpr; }
11446 bool isXLHSInRHSPart()
const {
return IsXLHSInRHSPart; }
11450 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11453 bool checkBinaryOperation(
BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11454 unsigned NoteId = 0);
11457bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11458 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11459 ExprAnalysisErrorCode ErrorFound = NoError;
11465 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11467 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11469 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11470 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11471 AtomicInnerBinOp->isBitwiseOp()) {
11472 Op = AtomicInnerBinOp->getOpcode();
11473 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11474 Expr *LHS = AtomicInnerBinOp->getLHS();
11475 Expr *RHS = AtomicInnerBinOp->getRHS();
11476 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11483 if (XId == LHSId) {
11485 IsXLHSInRHSPart =
true;
11486 }
else if (XId == RHSId) {
11488 IsXLHSInRHSPart =
false;
11490 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11491 ErrorRange = AtomicInnerBinOp->getSourceRange();
11492 NoteLoc =
X->getExprLoc();
11493 NoteRange =
X->getSourceRange();
11494 ErrorFound = NotAnUpdateExpression;
11497 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11498 ErrorRange = AtomicInnerBinOp->getSourceRange();
11499 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11501 ErrorFound = NotABinaryOperator;
11506 ErrorFound = NotABinaryExpression;
11513 ErrorFound = NotAnAssignmentOp;
11515 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11516 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11517 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11521 E =
X = UpdateExpr =
nullptr;
11522 return ErrorFound != NoError;
11525bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11527 ExprAnalysisErrorCode ErrorFound = NoError;
11538 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11539 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11540 if (AtomicBody->getType()->isScalarType() ||
11541 AtomicBody->isInstantiationDependent()) {
11542 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11543 AtomicBody->IgnoreParenImpCasts())) {
11546 AtomicCompAssignOp->getOpcode());
11547 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11548 E = AtomicCompAssignOp->getRHS();
11549 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11550 IsXLHSInRHSPart =
true;
11551 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11552 AtomicBody->IgnoreParenImpCasts())) {
11554 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11556 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11557 AtomicBody->IgnoreParenImpCasts())) {
11559 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11560 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11561 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11562 OpLoc = AtomicUnaryOp->getOperatorLoc();
11563 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11565 IsXLHSInRHSPart =
true;
11567 ErrorFound = NotAnUnaryIncDecExpression;
11568 ErrorLoc = AtomicUnaryOp->getExprLoc();
11569 ErrorRange = AtomicUnaryOp->getSourceRange();
11570 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11573 }
else if (!AtomicBody->isInstantiationDependent()) {
11574 ErrorFound = NotABinaryOrUnaryExpression;
11575 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11576 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11577 }
else if (AtomicBody->containsErrors()) {
11578 ErrorFound = NotAValidExpression;
11579 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11580 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11583 ErrorFound = NotAScalarType;
11584 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11585 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11588 ErrorFound = NotAnExpression;
11589 NoteLoc = ErrorLoc = S->getBeginLoc();
11590 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11592 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11593 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11594 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11598 E =
X = UpdateExpr =
nullptr;
11599 if (ErrorFound == NoError &&
E &&
X) {
11609 IsXLHSInRHSPart ? OVEExpr : OVEX);
11616 UpdateExpr =
Update.get();
11618 return ErrorFound != NoError;
11622llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11623 llvm::FoldingSetNodeID
Id;
11624 S->IgnoreParenImpCasts()->Profile(
Id, Context,
true);
11629bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11631 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11634class OpenMPAtomicCompareChecker {
11681 struct ErrorInfoTy {
11689 OpenMPAtomicCompareChecker(
Sema &S) : ContextRef(S.getASTContext()) {}
11692 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11694 Expr *getX()
const {
return X; }
11695 Expr *getE()
const {
return E; }
11696 Expr *getD()
const {
return D; }
11697 Expr *getCond()
const {
return C; }
11698 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11717 bool IsXBinopExpr =
true;
11720 bool checkCondUpdateStmt(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11723 bool checkCondExprStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11726 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11728 static bool CheckValue(
const Expr *
E, ErrorInfoTy &ErrorInfo,
11729 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11733 if (ShouldBeLValue && !
E->
isLValue()) {
11734 ErrorInfo.Error = ErrorTy::XNotLValue;
11735 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11742 ErrorInfo.Error = ErrorTy::NotScalar;
11743 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11748 ErrorInfo.Error = ErrorTy::NotInteger;
11749 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11758bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11759 ErrorInfoTy &ErrorInfo) {
11760 auto *Then = S->getThen();
11761 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11762 if (CS->body_empty()) {
11763 ErrorInfo.Error = ErrorTy::NoStmt;
11764 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11765 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11768 if (CS->size() > 1) {
11769 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11770 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11771 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11774 Then = CS->body_front();
11777 auto *BO = dyn_cast<BinaryOperator>(Then);
11779 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11780 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11781 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11784 if (BO->getOpcode() != BO_Assign) {
11785 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11786 ErrorInfo.ErrorLoc = BO->getExprLoc();
11787 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11788 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11794 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11795 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
11796 Expr *LHS =
nullptr;
11797 Expr *RHS =
nullptr;
11799 LHS = Cond->getLHS();
11800 RHS = Cond->getRHS();
11802 LHS =
Call->getArg(0);
11803 RHS =
Call->getArg(1);
11805 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11806 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11807 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11811 if ((Cond && Cond->getOpcode() == BO_EQ) ||
11812 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11815 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
11817 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
11820 ErrorInfo.Error = ErrorTy::InvalidComparison;
11821 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11822 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11823 S->getCond()->getSourceRange();
11826 }
else if ((Cond &&
11827 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11829 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11830 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11832 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
11833 checkIfTwoExprsAreSame(ContextRef,
E, RHS)) {
11835 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, LHS) &&
11836 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
11838 IsXBinopExpr =
false;
11840 ErrorInfo.Error = ErrorTy::InvalidComparison;
11841 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11842 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11843 S->getCond()->getSourceRange();
11847 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11848 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11849 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11853 if (S->getElse()) {
11854 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11855 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11856 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11863bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
11864 ErrorInfoTy &ErrorInfo) {
11865 auto *BO = dyn_cast<BinaryOperator>(S);
11867 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11868 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11869 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11872 if (BO->getOpcode() != BO_Assign) {
11873 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11874 ErrorInfo.ErrorLoc = BO->getExprLoc();
11875 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11876 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11882 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11884 ErrorInfo.Error = ErrorTy::NotCondOp;
11885 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11886 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11890 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
11891 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11892 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11893 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11894 CO->getFalseExpr()->getSourceRange();
11898 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11899 auto *
Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
11900 Expr *LHS =
nullptr;
11901 Expr *RHS =
nullptr;
11903 LHS = Cond->getLHS();
11904 RHS = Cond->getRHS();
11906 LHS =
Call->getArg(0);
11907 RHS =
Call->getArg(1);
11909 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11910 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11911 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11912 CO->getCond()->getSourceRange();
11916 if ((Cond && Cond->getOpcode() == BO_EQ) ||
11917 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11919 D = CO->getTrueExpr();
11920 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
11922 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
11925 ErrorInfo.Error = ErrorTy::InvalidComparison;
11926 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->
getExprLoc();
11927 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11928 CO->getCond()->getSourceRange();
11931 }
else if ((Cond &&
11932 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11934 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11935 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11937 E = CO->getTrueExpr();
11938 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
11939 checkIfTwoExprsAreSame(ContextRef,
E, RHS)) {
11941 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, LHS) &&
11942 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
11944 IsXBinopExpr =
false;
11946 ErrorInfo.Error = ErrorTy::InvalidComparison;
11947 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11948 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11949 CO->getCond()->getSourceRange();
11953 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11954 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11955 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11956 CO->getCond()->getSourceRange();
11963bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
11965 assert(
X &&
E &&
"X and E cannot be nullptr");
11967 if (!CheckValue(
X, ErrorInfo,
true))
11970 if (!CheckValue(
E, ErrorInfo,
false))
11973 if (
D && !CheckValue(
D, ErrorInfo,
false))
11979bool OpenMPAtomicCompareChecker::checkStmt(
11980 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11981 auto *CS = dyn_cast<CompoundStmt>(S);
11983 if (CS->body_empty()) {
11984 ErrorInfo.Error = ErrorTy::NoStmt;
11985 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11986 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11990 if (CS->size() != 1) {
11991 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11992 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11993 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11996 S = CS->body_front();
12001 if (
auto *IS = dyn_cast<IfStmt>(S)) {
12007 Res = checkCondUpdateStmt(IS, ErrorInfo);
12013 Res = checkCondExprStmt(S, ErrorInfo);
12019 return checkType(ErrorInfo);
12022class OpenMPAtomicCompareCaptureChecker final
12023 :
public OpenMPAtomicCompareChecker {
12025 OpenMPAtomicCompareCaptureChecker(
Sema &S) : OpenMPAtomicCompareChecker(S) {}
12027 Expr *getV()
const {
return V; }
12028 Expr *getR()
const {
return R; }
12029 bool isFailOnly()
const {
return IsFailOnly; }
12030 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
12033 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
12036 bool checkType(ErrorInfoTy &ErrorInfo);
12048 bool checkForm3(
IfStmt *S, ErrorInfoTy &ErrorInfo);
12052 bool checkForm45(
Stmt *S, ErrorInfoTy &ErrorInfo);
12059 bool IsFailOnly =
false;
12061 bool IsPostfixUpdate =
false;
12064bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12065 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12068 if (
V && !CheckValue(
V, ErrorInfo,
true))
12071 if (R && !CheckValue(R, ErrorInfo,
true,
true))
12077bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
12078 ErrorInfoTy &ErrorInfo) {
12081 auto *Then = S->getThen();
12082 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
12083 if (CS->body_empty()) {
12084 ErrorInfo.Error = ErrorTy::NoStmt;
12085 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12086 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12089 if (CS->size() > 1) {
12090 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12091 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12092 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12095 Then = CS->body_front();
12098 auto *BO = dyn_cast<BinaryOperator>(Then);
12100 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12101 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12102 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12105 if (BO->getOpcode() != BO_Assign) {
12106 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12107 ErrorInfo.ErrorLoc = BO->getExprLoc();
12108 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12109 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12116 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12117 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12118 Expr *LHS =
nullptr;
12119 Expr *RHS =
nullptr;
12121 LHS = Cond->getLHS();
12122 RHS = Cond->getRHS();
12124 LHS =
Call->getArg(0);
12125 RHS =
Call->getArg(1);
12127 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12128 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12129 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12132 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12133 (
Call &&
Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12134 ErrorInfo.Error = ErrorTy::NotEQ;
12135 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12136 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12140 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
12142 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
12145 ErrorInfo.Error = ErrorTy::InvalidComparison;
12146 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12147 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12153 if (!S->getElse()) {
12154 ErrorInfo.Error = ErrorTy::NoElse;
12155 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12156 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12160 auto *Else = S->getElse();
12161 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
12162 if (CS->body_empty()) {
12163 ErrorInfo.Error = ErrorTy::NoStmt;
12164 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12165 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12168 if (CS->size() > 1) {
12169 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12170 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12171 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12174 Else = CS->body_front();
12177 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12179 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12180 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12181 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12184 if (ElseBO->getOpcode() != BO_Assign) {
12185 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12186 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12187 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12188 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12192 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12193 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12194 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12195 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12196 ElseBO->getRHS()->getSourceRange();
12200 V = ElseBO->getLHS();
12202 return checkType(ErrorInfo);
12205bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
12206 ErrorInfoTy &ErrorInfo) {
12209 auto *CS = cast<CompoundStmt>(S);
12210 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
12211 auto *S1 = cast<BinaryOperator>(CS->body_front());
12212 auto *S2 = cast<IfStmt>(CS->body_back());
12213 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
12215 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12216 ErrorInfo.Error = ErrorTy::InvalidCondition;
12217 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12218 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12224 auto *Then = S2->getThen();
12225 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12226 if (ThenCS->body_empty()) {
12227 ErrorInfo.Error = ErrorTy::NoStmt;
12228 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12229 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12232 if (ThenCS->size() > 1) {
12233 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12234 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12235 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12238 Then = ThenCS->body_front();
12241 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12243 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12244 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12245 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12248 if (ThenBO->getOpcode() != BO_Assign) {
12249 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12250 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12251 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12252 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12256 X = ThenBO->getLHS();
12257 D = ThenBO->getRHS();
12259 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12260 if (BO->getOpcode() != BO_EQ) {
12261 ErrorInfo.Error = ErrorTy::NotEQ;
12262 ErrorInfo.ErrorLoc = BO->getExprLoc();
12263 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12264 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12270 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12272 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12275 ErrorInfo.Error = ErrorTy::InvalidComparison;
12276 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->
getExprLoc();
12277 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12281 if (S2->getElse()) {
12284 auto *Else = S2->getElse();
12285 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12286 if (ElseCS->body_empty()) {
12287 ErrorInfo.Error = ErrorTy::NoStmt;
12288 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12289 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12292 if (ElseCS->size() > 1) {
12293 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12294 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12295 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12298 Else = ElseCS->body_front();
12301 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12303 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12304 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12305 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12308 if (ElseBO->getOpcode() != BO_Assign) {
12309 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12310 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12311 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12312 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12315 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12316 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12317 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12318 ErrorInfo.NoteLoc =
X->getExprLoc();
12319 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12320 ErrorInfo.NoteRange =
X->getSourceRange();
12324 V = ElseBO->getLHS();
12327 return checkType(ErrorInfo);
12330bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12331 ErrorInfoTy &ErrorInfo) {
12333 if (
auto *IS = dyn_cast<IfStmt>(S))
12334 return checkForm3(IS, ErrorInfo);
12336 auto *CS = dyn_cast<CompoundStmt>(S);
12338 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12339 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12340 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12343 if (CS->body_empty()) {
12344 ErrorInfo.Error = ErrorTy::NoStmt;
12345 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12346 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12351 if (CS->size() == 1) {
12352 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12354 ErrorInfo.Error = ErrorTy::NotIfStmt;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12361 return checkForm3(IS, ErrorInfo);
12362 }
else if (CS->size() == 2) {
12363 auto *S1 = CS->body_front();
12364 auto *S2 = CS->body_back();
12366 Stmt *UpdateStmt =
nullptr;
12367 Stmt *CondUpdateStmt =
nullptr;
12368 Stmt *CondExprStmt =
nullptr;
12370 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12376 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12377 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12379 if (isa<IfStmt>(S2))
12380 return checkForm45(CS, ErrorInfo);
12385 IsPostfixUpdate =
true;
12387 if (isa<IfStmt>(S2)) {
12389 CondUpdateStmt = S2;
12398 CondUpdateStmt = S1;
12401 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12402 auto *IS = dyn_cast<IfStmt>(CUS);
12404 ErrorInfo.Error = ErrorTy::NotIfStmt;
12405 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12406 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12410 return checkCondUpdateStmt(IS, ErrorInfo);
12414 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12415 auto *BO = dyn_cast<BinaryOperator>(US);
12417 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12418 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12419 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12422 if (BO->getOpcode() != BO_Assign) {
12423 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12424 ErrorInfo.ErrorLoc = BO->getExprLoc();
12425 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12426 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12429 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12430 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12431 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12433 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12438 this->V = BO->getLHS();
12443 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12445 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12447 if (!CheckUpdateStmt(UpdateStmt))
12450 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12451 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12452 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12456 return checkType(ErrorInfo);
12467 DSAStack->addAtomicDirectiveLoc(StartLoc);
12480 bool MutexClauseEncountered =
false;
12481 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12483 switch (
C->getClauseKind()) {
12487 MutexClauseEncountered =
true;
12490 case OMPC_compare: {
12491 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12492 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12494 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12497 AtomicKind =
C->getClauseKind();
12498 AtomicKindLoc =
C->getBeginLoc();
12499 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12500 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12502 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12510 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12511 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12522 case OMPC_relaxed: {
12523 if (MemOrderKind != OMPC_unknown) {
12524 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12525 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12527 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12530 MemOrderKind =
C->getClauseKind();
12531 MemOrderLoc =
C->getBeginLoc();
12539 llvm_unreachable(
"unknown clause is encountered");
12542 bool IsCompareCapture =
false;
12543 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12544 EncounteredAtomicKinds.contains(OMPC_capture)) {
12545 IsCompareCapture =
true;
12546 AtomicKind = OMPC_compare;
12555 if ((AtomicKind == OMPC_read &&
12556 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12557 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12558 AtomicKind == OMPC_unknown) &&
12559 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12561 if (AtomicKind == OMPC_unknown)
12563 Diag(
Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12565 << (AtomicKind == OMPC_unknown ? 1 : 0)
12567 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12571 Stmt *Body = AStmt;
12572 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12573 Body = EWC->getSubExpr();
12578 Expr *UE =
nullptr;
12580 Expr *CE =
nullptr;
12582 bool IsXLHSInRHSPart =
false;
12583 bool IsPostfixUpdate =
false;
12584 bool IsFailOnly =
false;
12607 if (AtomicKind == OMPC_read) {
12614 } ErrorFound = NoError;
12619 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12620 const auto *AtomicBinOp =
12621 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12622 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12625 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12626 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12627 if (!
X->isLValue() || !
V->isLValue()) {
12628 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12629 ErrorFound = NotAnLValue;
12635 }
else if (!
X->isInstantiationDependent() ||
12636 !
V->isInstantiationDependent()) {
12637 const Expr *NotScalarExpr =
12638 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12641 ErrorFound = NotAScalarType;
12647 }
else if (!AtomicBody->isInstantiationDependent()) {
12648 ErrorFound = NotAnAssignmentOp;
12649 ErrorLoc = AtomicBody->getExprLoc();
12650 ErrorRange = AtomicBody->getSourceRange();
12652 : AtomicBody->getExprLoc();
12654 : AtomicBody->getSourceRange();
12657 ErrorFound = NotAnExpression;
12659 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12661 if (ErrorFound != NoError) {
12662 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12664 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12665 << ErrorFound << NoteRange;
12670 }
else if (AtomicKind == OMPC_write) {
12677 } ErrorFound = NoError;
12682 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12683 const auto *AtomicBinOp =
12684 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12685 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12688 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12690 if (!
X->isLValue()) {
12691 ErrorFound = NotAnLValue;
12694 NoteLoc =
X->getExprLoc();
12695 NoteRange =
X->getSourceRange();
12697 }
else if (!
X->isInstantiationDependent() ||
12699 const Expr *NotScalarExpr =
12700 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12703 ErrorFound = NotAScalarType;
12709 }
else if (!AtomicBody->isInstantiationDependent()) {
12710 ErrorFound = NotAnAssignmentOp;
12711 ErrorLoc = AtomicBody->getExprLoc();
12712 ErrorRange = AtomicBody->getSourceRange();
12714 : AtomicBody->getExprLoc();
12716 : AtomicBody->getSourceRange();
12719 ErrorFound = NotAnExpression;
12721 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12723 if (ErrorFound != NoError) {
12724 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12726 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12727 << ErrorFound << NoteRange;
12732 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12741 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12742 if (Checker.checkStatement(
12744 (AtomicKind == OMPC_update)
12745 ? diag::err_omp_atomic_update_not_expression_statement
12746 : diag::err_omp_atomic_not_expression_statement,
12747 diag::note_omp_atomic_update))
12750 E = Checker.getExpr();
12751 X = Checker.getX();
12752 UE = Checker.getUpdateExpr();
12753 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12755 }
else if (AtomicKind == OMPC_capture) {
12758 NotACompoundStatement,
12759 NotTwoSubstatements,
12760 NotASpecificExpression,
12762 } ErrorFound = NoError;
12765 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12774 const auto *AtomicBinOp =
12775 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12776 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12779 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12780 if (Checker.checkStatement(
12781 Body, diag::err_omp_atomic_capture_not_expression_statement,
12782 diag::note_omp_atomic_update))
12784 E = Checker.getExpr();
12785 X = Checker.getX();
12786 UE = Checker.getUpdateExpr();
12787 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12788 IsPostfixUpdate = Checker.isPostfixUpdate();
12789 }
else if (!AtomicBody->isInstantiationDependent()) {
12790 ErrorLoc = AtomicBody->getExprLoc();
12791 ErrorRange = AtomicBody->getSourceRange();
12793 : AtomicBody->getExprLoc();
12795 : AtomicBody->getSourceRange();
12796 ErrorFound = NotAnAssignmentOp;
12798 if (ErrorFound != NoError) {
12799 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12801 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12805 UE =
V =
E =
X =
nullptr;
12823 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
12825 if (CS->size() == 2) {
12827 Stmt *Second = CS->body_back();
12828 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
12829 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12830 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12831 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12833 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12834 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12836 if (IsUpdateExprFound) {
12837 BinOp = dyn_cast<BinaryOperator>(
First);
12838 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12850 llvm::FoldingSetNodeID XId, PossibleXId;
12851 Checker.getX()->
Profile(XId, Context,
true);
12852 PossibleX->
Profile(PossibleXId, Context,
true);
12853 IsUpdateExprFound = XId == PossibleXId;
12854 if (IsUpdateExprFound) {
12856 X = Checker.getX();
12857 E = Checker.getExpr();
12858 UE = Checker.getUpdateExpr();
12859 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12860 IsPostfixUpdate =
true;
12863 if (!IsUpdateExprFound) {
12864 IsUpdateExprFound = !Checker.checkStatement(
First);
12866 if (IsUpdateExprFound) {
12867 BinOp = dyn_cast<BinaryOperator>(Second);
12868 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12870 if (IsUpdateExprFound &&
12881 llvm::FoldingSetNodeID XId, PossibleXId;
12882 Checker.getX()->
Profile(XId, Context,
true);
12883 PossibleX->
Profile(PossibleXId, Context,
true);
12884 IsUpdateExprFound = XId == PossibleXId;
12885 if (IsUpdateExprFound) {
12887 X = Checker.getX();
12888 E = Checker.getExpr();
12889 UE = Checker.getUpdateExpr();
12890 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12891 IsPostfixUpdate =
false;
12895 if (!IsUpdateExprFound) {
12897 auto *FirstExpr = dyn_cast<Expr>(
First);
12898 auto *SecondExpr = dyn_cast<Expr>(Second);
12899 if (!FirstExpr || !SecondExpr ||
12900 !(FirstExpr->isInstantiationDependent() ||
12901 SecondExpr->isInstantiationDependent())) {
12902 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
12903 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12904 ErrorFound = NotAnAssignmentOp;
12905 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12906 :
First->getBeginLoc();
12907 NoteRange = ErrorRange = FirstBinOp
12908 ? FirstBinOp->getSourceRange()
12911 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12912 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12913 ErrorFound = NotAnAssignmentOp;
12914 NoteLoc = ErrorLoc = SecondBinOp
12915 ? SecondBinOp->getOperatorLoc()
12917 NoteRange = ErrorRange =
12918 SecondBinOp ? SecondBinOp->getSourceRange()
12921 Expr *PossibleXRHSInFirst =
12923 Expr *PossibleXLHSInSecond =
12925 llvm::FoldingSetNodeID X1Id, X2Id;
12926 PossibleXRHSInFirst->
Profile(X1Id, Context,
12928 PossibleXLHSInSecond->
Profile(X2Id, Context,
12930 IsUpdateExprFound = X1Id == X2Id;
12931 if (IsUpdateExprFound) {
12932 V = FirstBinOp->getLHS();
12933 X = SecondBinOp->getLHS();
12934 E = SecondBinOp->getRHS();
12936 IsXLHSInRHSPart =
false;
12937 IsPostfixUpdate =
true;
12939 ErrorFound = NotASpecificExpression;
12940 ErrorLoc = FirstBinOp->getExprLoc();
12941 ErrorRange = FirstBinOp->getSourceRange();
12942 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12943 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12951 NoteRange = ErrorRange =
12953 ErrorFound = NotTwoSubstatements;
12957 NoteRange = ErrorRange =
12959 ErrorFound = NotACompoundStatement;
12962 if (ErrorFound != NoError) {
12963 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12965 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12969 UE =
V =
E =
X =
nullptr;
12970 }
else if (AtomicKind == OMPC_compare) {
12971 if (IsCompareCapture) {
12972 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12973 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
12974 if (!Checker.checkStmt(Body, ErrorInfo)) {
12975 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12976 << ErrorInfo.ErrorRange;
12977 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12978 << ErrorInfo.Error << ErrorInfo.NoteRange;
12981 X = Checker.getX();
12982 E = Checker.getE();
12983 D = Checker.getD();
12984 CE = Checker.getCond();
12985 V = Checker.getV();
12986 R = Checker.getR();
12988 IsXLHSInRHSPart = Checker.isXBinopExpr();
12989 IsFailOnly = Checker.isFailOnly();
12990 IsPostfixUpdate = Checker.isPostfixUpdate();
12992 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12993 OpenMPAtomicCompareChecker Checker(
SemaRef);
12994 if (!Checker.checkStmt(Body, ErrorInfo)) {
12995 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12996 << ErrorInfo.ErrorRange;
12997 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12998 << ErrorInfo.Error << ErrorInfo.NoteRange;
13001 X = Checker.getX();
13002 E = Checker.getE();
13003 D = Checker.getD();
13004 CE = Checker.getCond();
13010 auto *It = find_if(Clauses, [](
OMPClause *
C) {
13011 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13013 if (It != Clauses.end()) {
13014 auto *Cond = dyn_cast<BinaryOperator>(CE);
13015 if (Cond->getOpcode() != BO_EQ) {
13016 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13018 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13019 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
13021 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13022 << ErrorInfo.ErrorRange;
13027 IsXLHSInRHSPart = Checker.isXBinopExpr();
13034 Context, StartLoc, EndLoc, Clauses, AStmt,
13035 {
X,
V, R,
E, UE,
D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13051 if (
DSAStack->hasInnerTeamsRegion()) {
13053 bool OMPTeamsFound =
true;
13054 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
13055 auto I = CS->body_begin();
13056 while (I != CS->body_end()) {
13057 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13059 if (!IsTeams || I != CS->body_begin()) {
13060 OMPTeamsFound =
false;
13061 if (IsTeams && I != CS->body_begin()) {
13070 assert(I != CS->body_end() &&
"Not found statement");
13073 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13076 if (!OMPTeamsFound) {
13077 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13079 diag::note_omp_nested_teams_construct_here);
13080 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13081 << isa<OMPExecutableDirective>(S);
13115 unsigned NestedLoopCount =
13118 VarsWithImplicitDSA, B);
13119 if (NestedLoopCount == 0)
13126 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13133 return llvm::any_of(
13134 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
13137template <
typename... Params>
13139 const Params... ClauseTypes) {
13146 if (
auto *TC = dyn_cast<OMPToClause>(
C))
13147 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
13148 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13149 (VD->isExternallyVisible() &&
13150 VD->getVisibility() != HiddenVisibility);
13152 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
13153 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
13154 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13155 (VD->isExternallyVisible() &&
13156 VD->getVisibility() != HiddenVisibility);
13170 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13175 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13177 !
hasClauses(Clauses, OMPC_use_device_addr))) {
13180 Expected =
"'map' or 'use_device_ptr'";
13182 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
13184 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13185 <<
Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13207 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13209 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13229 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13230 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13246 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13247 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13252 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13262template <
typename ClauseType>
13265 unsigned MaxNum,
unsigned Diag) {
13266 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13267 if (ClauseItr == Clauses.end())
13269 const auto *
C = cast<ClauseType>(*ClauseItr);
13270 auto VarList =
C->getVarRefs();
13271 if (VarList.size() > MaxNum) {
13272 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13286 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13287 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13288 !checkNumExprsInClause<OMPThreadLimitClause>(
13289 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13294 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13298 DSAStack->setParentTeamsRegionLoc(StartLoc);
13307 if (
DSAStack->isParentNowaitRegion()) {
13308 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13311 if (
DSAStack->isParentOrderedRegion()) {
13312 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13316 EndLoc, CancelRegion);
13322 if (
DSAStack->isParentNowaitRegion()) {
13323 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13326 if (
DSAStack->isParentOrderedRegion()) {
13327 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13330 DSAStack->setParentCancelRegion(
true);
13337 const OMPClause *ReductionClause =
nullptr;
13338 const OMPClause *NogroupClause =
nullptr;
13340 if (
C->getClauseKind() == OMPC_reduction) {
13341 ReductionClause =
C;
13346 if (
C->getClauseKind() == OMPC_nogroup) {
13348 if (ReductionClause)
13353 if (ReductionClause && NogroupClause) {
13354 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13368 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13372 unsigned NestedLoopCount =
13375 *
DSAStack, VarsWithImplicitDSA, B);
13376 if (NestedLoopCount == 0)
13380 "omp for loop exprs were not built");
13386 {OMPC_grainsize, OMPC_num_tasks}))
13396 NestedLoopCount, Clauses, AStmt, B,
13409 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13413 unsigned NestedLoopCount =
13416 VarsWithImplicitDSA, B);
13417 if (NestedLoopCount == 0)
13427 {OMPC_grainsize, OMPC_num_tasks}))
13438 NestedLoopCount, Clauses, AStmt, B);
13447 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13451 unsigned NestedLoopCount =
13454 *
DSAStack, VarsWithImplicitDSA, B);
13455 if (NestedLoopCount == 0)
13459 "omp for loop exprs were not built");
13465 {OMPC_grainsize, OMPC_num_tasks}))
13475 NestedLoopCount, Clauses, AStmt, B,
13485 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13489 unsigned NestedLoopCount =
13492 *
DSAStack, VarsWithImplicitDSA, B);
13493 if (NestedLoopCount == 0)
13497 "omp for loop exprs were not built");
13503 {OMPC_grainsize, OMPC_num_tasks}))
13513 NestedLoopCount, Clauses, AStmt, B,
13526 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13530 unsigned NestedLoopCount =
13533 VarsWithImplicitDSA, B);
13534 if (NestedLoopCount == 0)
13544 {OMPC_grainsize, OMPC_num_tasks}))
13555 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13567 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13571 unsigned NestedLoopCount =
13574 VarsWithImplicitDSA, B);
13575 if (NestedLoopCount == 0)
13585 {OMPC_grainsize, OMPC_num_tasks}))
13596 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13614 VarsWithImplicitDSA, B);
13615 if (NestedLoopCount == 0)
13619 "omp for loop exprs were not built");
13625 {OMPC_grainsize, OMPC_num_tasks}))
13634 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13653 VarsWithImplicitDSA, B);
13654 if (NestedLoopCount == 0)
13658 "omp for loop exprs were not built");
13664 {OMPC_grainsize, OMPC_num_tasks}))
13673 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13684 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13692 VarsWithImplicitDSA, B);
13693 if (NestedLoopCount == 0)
13703 {OMPC_grainsize, OMPC_num_tasks}))
13714 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13724 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13732 VarsWithImplicitDSA, B);
13733 if (NestedLoopCount == 0)
13743 {OMPC_grainsize, OMPC_num_tasks}))
13754 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13763 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13767 unsigned NestedLoopCount =
13771 if (NestedLoopCount == 0)
13775 "omp for loop exprs were not built");
13779 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13780 return DistributeDirective;
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13803 "omp for loop exprs were not built");
13806 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13817 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13825 VarsWithImplicitDSA, B);
13826 if (NestedLoopCount == 0)
13836 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13851 unsigned NestedLoopCount =
13855 if (NestedLoopCount == 0)
13865 NestedLoopCount, Clauses, AStmt, B);
13883 VarsWithImplicitDSA, B);
13884 if (NestedLoopCount == 0)
13894 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13908 unsigned NestedLoopCount =
13911 VarsWithImplicitDSA, B);
13912 if (NestedLoopCount == 0)
13922 NestedLoopCount, Clauses, AStmt, B);
13937 unsigned NestedLoopCount =
13941 if (NestedLoopCount == 0)
13945 "omp teams distribute loop exprs were not built");
13947 DSAStack->setParentTeamsRegionLoc(StartLoc);
13950 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13968 VarsWithImplicitDSA, B);
13969 if (NestedLoopCount == 0)
13978 DSAStack->setParentTeamsRegionLoc(StartLoc);
13981 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13991 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13999 VarsWithImplicitDSA, B);
14000 if (NestedLoopCount == 0)
14009 DSAStack->setParentTeamsRegionLoc(StartLoc);
14012 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14022 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14030 VarsWithImplicitDSA, B);
14032 if (NestedLoopCount == 0)
14036 "omp for loop exprs were not built");
14038 DSAStack->setParentTeamsRegionLoc(StartLoc);
14041 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14054 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
14056 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
14058 return C->getClauseKind() == OMPC_ompx_bare;
14061 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14066 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14067 unsigned DiagNo = HasBareClause
14068 ? diag::err_ompx_more_than_three_expr_not_allowed
14069 : diag::err_omp_multi_expr_not_allowed;
14070 if (!checkNumExprsInClause<OMPNumTeamsClause>(*
this, Clauses,
14071 ClauseMaxNumExprs, DiagNo) ||
14072 !checkNumExprsInClause<OMPThreadLimitClause>(*
this, Clauses,
14073 ClauseMaxNumExprs, DiagNo))
14086 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14087 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14088 !checkNumExprsInClause<OMPThreadLimitClause>(
14089 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14101 VarsWithImplicitDSA, B);
14102 if (NestedLoopCount == 0)
14106 "omp target teams distribute loop exprs were not built");
14109 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14118 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14119 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14120 !checkNumExprsInClause<OMPThreadLimitClause>(
14121 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14125 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14133 VarsWithImplicitDSA, B);
14134 if (NestedLoopCount == 0)
14141 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14151 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14152 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14153 !checkNumExprsInClause<OMPThreadLimitClause>(
14154 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14158 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14163 unsigned NestedLoopCount =
14168 if (NestedLoopCount == 0)
14178 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14187 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14188 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
14189 !checkNumExprsInClause<OMPThreadLimitClause>(
14190 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
14194 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14202 VarsWithImplicitDSA, B);
14203 if (NestedLoopCount == 0)
14213 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14216bool SemaOpenMP::checkTransformableLoopNest(
14220 OriginalInits.emplace_back();
14223 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14225 VarsWithInheritedDSAType TmpDSA;
14226 unsigned SingleNumLoops =
14227 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14228 TmpDSA, LoopHelpers[Cnt]);
14229 if (SingleNumLoops == 0)
14231 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14232 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14233 OriginalInits.back().push_back(For->getInit());
14234 Body = For->getBody();
14236 assert(isa<CXXForRangeStmt>(CurStmt) &&
14237 "Expected canonical for or range-based for loops.");
14238 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14239 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14240 Body = CXXFor->getBody();
14242 OriginalInits.emplace_back();
14246 Stmt *DependentPreInits;
14247 if (
auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14248 DependentPreInits = Dir->getPreInits();
14249 else if (
auto *Dir = dyn_cast<OMPStripeDirective>(Transform))
14250 DependentPreInits = Dir->getPreInits();
14251 else if (
auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14252 DependentPreInits = Dir->getPreInits();
14253 else if (
auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14254 DependentPreInits = Dir->getPreInits();
14255 else if (
auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14256 DependentPreInits = Dir->getPreInits();
14258 llvm_unreachable(
"Unhandled loop transformation");
14262 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14263 OriginalInits.pop_back();
14275 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14276 Stmt *RangeInit = CXXRangeFor->getInit();
14278 PreInits.push_back(RangeInit);
14280 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14285 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14291 llvm::append_range(PreInits, OriginalInit);
14294 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.
PreInits)) {
14295 PreInits.push_back(
new (Context)
DeclStmt(
14296 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14301 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14302 if (isa<OMPCapturedExprDecl>(CounterDecl))
14303 PreInits.push_back(
new (Context)
DeclStmt(
14311 size_t NumLoops = LoopStmts.size();
14313 AStmt,
false, NumLoops,
14314 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14315 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14316 LoopStmts[Cnt] = CurStmt;
14319 assert(!is_contained(LoopStmts,
nullptr) &&
14320 "Expecting a loop statement for each affected loop");
14338 const auto *SizesClause =
14339 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14340 if (!SizesClause ||
14341 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *
E) { return !E; }))
14343 unsigned NumLoops = SizesClause->getNumSizes();
14351 Stmt *Body =
nullptr;
14353 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14360 NumLoops, AStmt,
nullptr,
nullptr);
14362 assert(LoopHelpers.size() == NumLoops &&
14363 "Expecting loop iteration space dimensionality to match number of "
14365 assert(OriginalInits.size() == NumLoops &&
14366 "Expecting loop iteration space dimensionality to match number of "
14374 CaptureVars CopyTransformer(
SemaRef);
14379 FloorIndVars.resize(NumLoops);
14380 TileIndVars.resize(NumLoops);
14381 for (
unsigned I = 0; I < NumLoops; ++I) {
14384 assert(LoopHelper.
Counters.size() == 1 &&
14385 "Expect single-dimensional loop iteration space");
14386 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14387 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14393 std::string FloorCntName =
14394 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14397 FloorIndVars[I] = FloorCntDecl;
14402 std::string TileCntName =
14403 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14408 auto *TileCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
14409 TileCntDecl->setDeclName(
14411 TileIndVars[I] = TileCntDecl;
14419 Stmt *Inner = Body;
14421 auto MakeDimTileSize = [&
SemaRef = this->
SemaRef, &CopyTransformer, &Context,
14422 SizesClause, CurScope](
int I) ->
Expr * {
14423 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14428 if (isa<ConstantExpr>(DimTileSizeExpr))
14429 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14450 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14454 CurScope, {}, BO_LE,
14458 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14464 for (
int I = NumLoops - 1; I >= 0; --I) {
14467 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters[0]);
14469 Stmt *LoopStmt = LoopStmts[I];
14474 auto MakeTileIVRef = [&
SemaRef = this->
SemaRef, &TileIndVars, I, IVTy,
14477 OrigCntVar->getExprLoc());
14484 .DefaultLvalueConversion(
14488 Decl *CounterDecl = TileIndVars[I];
14491 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14497 Expr *DimTileSize = MakeDimTileSize(I);
14508 NumIterations, EndOfTile.
get());
14513 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
14514 if (!MinTileAndIterSpace.
isUsable())
14518 MakeTileIVRef(), MinTileAndIterSpace.
get());
14524 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeTileIVRef());
14545 BodyParts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14546 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14547 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14548 BodyParts.push_back(Inner);
14550 Inner->getBeginLoc(), Inner->getEndLoc());
14551 Inner =
new (Context)
14558 for (
int I = NumLoops - 1; I >= 0; --I) {
14559 auto &LoopHelper = LoopHelpers[I];
14560 Expr *NumIterations = LoopHelper.NumIterations;
14561 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14569 Decl *CounterDecl = FloorIndVars[I];
14578 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14585 Expr *DimTileSize = MakeDimTileSize(I);
14589 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14595 Inner =
new (Context)
14597 IncrStmt.
get(), Inner, LoopHelper.Init->getBeginLoc(),
14598 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14613 const auto *SizesClause =
14614 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14615 if (!SizesClause ||
14616 llvm::any_of(SizesClause->getSizesRefs(), [](
const Expr *SizeExpr) {
14617 return !SizeExpr || SizeExpr->containsErrors();
14620 unsigned NumLoops = SizesClause->getNumSizes();
14628 Stmt *Body =
nullptr;
14630 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
14631 Body, OriginalInits))
14637 NumLoops, AStmt,
nullptr,
nullptr);
14639 assert(LoopHelpers.size() == NumLoops &&
14640 "Expecting loop iteration space dimensionality to match number of "
14642 assert(OriginalInits.size() == NumLoops &&
14643 "Expecting loop iteration space dimensionality to match number of "
14651 CaptureVars CopyTransformer(
SemaRef);
14656 FloorIndVars.resize(NumLoops);
14657 StripeIndVars.resize(NumLoops);
14658 for (
unsigned I : llvm::seq<unsigned>(NumLoops)) {
14661 assert(LoopHelper.
Counters.size() == 1 &&
14662 "Expect single-dimensional loop iteration space");
14663 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14664 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14670 std::string FloorCntName =
14671 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14674 FloorIndVars[I] = FloorCntDecl;
14679 std::string StripeCntName =
14680 (Twine(
".stripe_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14685 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
14686 StripeCntDecl->setDeclName(
14688 StripeIndVars[I] = StripeCntDecl;
14696 Stmt *Inner = Body;
14698 auto MakeDimStripeSize = [&](
int I) ->
Expr * {
14699 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
14700 if (isa<ConstantExpr>(DimStripeSizeExpr))
14701 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
14722 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14726 CurScope, {}, BO_LE,
14730 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
14736 for (
int I = NumLoops - 1; I >= 0; --I) {
14739 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters[0]);
14741 Stmt *LoopStmt = LoopStmts[I];
14747 .DefaultLvalueConversion(
14751 Decl *CounterDecl = StripeIndVars[I];
14754 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14763 MakeDimStripeSize(I));
14768 NumIterations, EndOfStripe.
get());
14773 IsPartialStripe.
get(), NumIterations, EndOfStripe.
get());
14774 if (!MinStripeAndIterSpace.
isUsable())
14779 MinStripeAndIterSpace.
get());
14807 BodyParts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14808 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14809 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14810 BodyParts.push_back(Inner);
14812 Inner->getBeginLoc(), Inner->getEndLoc());
14813 Inner =
new (Context)
14820 for (
int I = NumLoops - 1; I >= 0; --I) {
14821 auto &LoopHelper = LoopHelpers[I];
14822 Expr *NumIterations = LoopHelper.NumIterations;
14823 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14831 Decl *CounterDecl = FloorIndVars[I];
14840 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14848 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14850 MakeDimStripeSize(I));
14854 Inner =
new (Context)
14856 IncrStmt.
get(), Inner, LoopHelper.Init->getBeginLoc(),
14857 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14861 NumLoops, AStmt, Inner,
14876 {OMPC_partial, OMPC_full}))
14880 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14882 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14883 assert(!(FullClause && PartialClause) &&
14884 "mutual exclusivity must have been checked before");
14886 constexpr unsigned NumLoops = 1;
14887 Stmt *Body =
nullptr;
14891 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14892 Body, OriginalInits))
14895 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14900 NumGeneratedLoops,
nullptr,
nullptr);
14902 assert(LoopHelpers.size() == NumLoops &&
14903 "Expecting a single-dimensional loop iteration space");
14904 assert(OriginalInits.size() == NumLoops &&
14905 "Expecting a single-dimensional loop iteration space");
14913 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14915 <<
"#pragma omp unroll full";
14923 if (NumGeneratedLoops == 0)
14925 NumGeneratedLoops,
nullptr,
nullptr);
14970 Stmt *LoopStmt =
nullptr;
14975 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14977 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14978 QualType IVTy = IterationVarRef->getType();
14979 assert(LoopHelper.
Counters.size() == 1 &&
14980 "Expecting a single-dimensional loop iteration space");
14981 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14988 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14989 FactorLoc = FactorVal->getExprLoc();
14994 assert(Factor > 0 &&
"Expected positive unroll factor");
14995 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
15007 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15008 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
15009 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
15014 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
15020 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15022 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
15028 CaptureVars CopyTransformer(
SemaRef);
15029 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15052 MakeOuterRef(), MakeFactorExpr());
15057 MakeInnerRef(), EndOfTile.
get());
15062 MakeInnerRef(), MakeNumIterations());
15067 InnerCond1.
get(), InnerCond2.
get());
15073 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeInnerRef());
15079 InnerBodyStmts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
15080 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15081 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15082 InnerBodyStmts.push_back(Body);
15086 ForStmt *InnerFor =
new (Context)
15087 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
15103 LoopHintAttr *UnrollHintAttr =
15104 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15105 LoopHintAttr::Numeric, MakeFactorExpr());
15122 MakeOuterRef(), MakeNumIterations());
15129 MakeOuterRef(), MakeFactorExpr());
15134 ForStmt *OuterFor =
new (Context)
15135 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
15140 NumGeneratedLoops, OuterFor,
15154 constexpr unsigned NumLoops = 1;
15155 Stmt *Body =
nullptr;
15159 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15160 Body, OriginalInits))
15167 NumLoops,
nullptr,
nullptr);
15169 assert(LoopHelpers.size() == NumLoops &&
15170 "Expecting a single-dimensional loop iteration space");
15171 assert(OriginalInits.size() == NumLoops &&
15172 "Expecting a single-dimensional loop iteration space");
15176 Stmt *LoopStmt =
nullptr;
15181 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15183 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
15184 QualType IVTy = IterationVarRef->getType();
15186 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
15199 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15201 ForwardIVName += OrigVarName;
15203 ReversedIVName += OrigVarName;
15236 CaptureVars CopyTransformer(
SemaRef);
15237 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
15245 auto MakeForwardRef = [&
SemaRef = this->
SemaRef, ForwardIVDecl, IVTy,
15252 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15253 ReversedIVDecl->setDeclName(
15261 ForwardIVDecl->
getType(), OrigVarLoc);
15265 if (!
Init.isUsable())
15274 MakeForwardRef(), MakeNumIterations());
15283 UO_PreInc, MakeForwardRef());
15294 MakeNumIterations(), One);
15302 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15310 BodyStmts.reserve(LoopHelper.
Updates.size() + 2 +
15311 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15312 BodyStmts.push_back(InitReversed.
get());
15313 llvm::append_range(BodyStmts, LoopHelper.
Updates);
15314 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15315 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15316 BodyStmts.push_back(Body);
15317 auto *ReversedBody =
15322 auto *ReversedFor =
new (Context)
15344 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15345 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
15349 Stmt *Body =
nullptr;
15351 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15352 LoopHelpers, Body, OriginalInits))
15358 NumLoops, AStmt,
nullptr,
nullptr);
15362 if (PermutationClause &&
15363 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
15366 assert(LoopHelpers.size() == NumLoops &&
15367 "Expecting loop iteration space dimensionaly to match number of "
15369 assert(OriginalInits.size() == NumLoops &&
15370 "Expecting loop iteration space dimensionaly to match number of "
15375 if (!PermutationClause) {
15376 Permutation = {1, 0};
15379 llvm::BitVector Flags(PermArgs.size());
15380 for (
Expr *PermArg : PermArgs) {
15381 std::optional<llvm::APSInt> PermCstExpr =
15382 PermArg->getIntegerConstantExpr(Context);
15385 uint64_t PermInt = PermCstExpr->getZExtValue();
15386 assert(1 <= PermInt && PermInt <= NumLoops &&
15387 "Must be a permutation; diagnostic emitted in "
15388 "ActOnOpenMPPermutationClause");
15389 if (Flags[PermInt - 1]) {
15390 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15391 Diag(PermArg->getExprLoc(),
15392 diag::err_omp_interchange_permutation_value_repeated)
15393 << PermInt << ExprRange;
15396 Flags[PermInt - 1] =
true;
15398 Permutation.push_back(PermInt - 1);
15401 if (Permutation.size() != NumLoops)
15406 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
15407 auto [Idx, Arg] =
P;
15411 NumLoops, AStmt, AStmt,
nullptr);
15419 for (
auto I : llvm::seq<int>(NumLoops)) {
15422 assert(LoopHelper.
Counters.size() == 1 &&
15423 "Single-dimensional loop iteration space expected");
15430 CaptureVars CopyTransformer(
SemaRef);
15435 Stmt *Inner = Body;
15436 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15438 uint64_t SourceIdx = Permutation[TargetIdx];
15440 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15441 assert(SourceHelper.
Counters.size() == 1 &&
15442 "Single-dimensional loop iteration space expected");
15443 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.
Counters.front());
15449 "Expected the logical iteration counter to be an integer");
15451 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15456 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
15458 CopyTransformer.TransformExpr(SourceHelper.
NumIterations));
15465 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
15466 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
15467 PermutedCntDecl->setDeclName(
15469 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15470 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15479 if (!
Zero.isUsable())
15485 OrigCntVar->getEndLoc());
15495 MakePermutedRef(), MakeNumIterations());
15504 CurScope, SourceHelper.
Inc->
getExprLoc(), UO_PreInc, MakePermutedRef());
15510 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15511 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15512 BodyParts.push_back(Inner);
15514 Inner->getBeginLoc(), Inner->getEndLoc());
15515 Inner =
new (Context)
ForStmt(
15516 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
15522 NumLoops, AStmt, Inner,
15542 case OMPC_allocator:
15545 case OMPC_collapse:
15551 case OMPC_priority:
15563 case OMPC_novariants:
15566 case OMPC_nocontext:
15581 case OMPC_ompx_dyn_cgroup_mem:
15587 case OMPC_grainsize:
15588 case OMPC_num_tasks:
15589 case OMPC_num_threads:
15593 case OMPC_proc_bind:
15594 case OMPC_schedule:
15596 case OMPC_firstprivate:
15597 case OMPC_lastprivate:
15599 case OMPC_reduction:
15600 case OMPC_task_reduction:
15601 case OMPC_in_reduction:
15605 case OMPC_copyprivate:
15608 case OMPC_mergeable:
15609 case OMPC_threadprivate:
15611 case OMPC_allocate:
15628 case OMPC_dist_schedule:
15629 case OMPC_defaultmap:
15634 case OMPC_use_device_ptr:
15635 case OMPC_use_device_addr:
15636 case OMPC_is_device_ptr:
15637 case OMPC_unified_address:
15638 case OMPC_unified_shared_memory:
15639 case OMPC_reverse_offload:
15640 case OMPC_dynamic_allocators:
15641 case OMPC_atomic_default_mem_order:
15642 case OMPC_self_maps:
15643 case OMPC_device_type:
15645 case OMPC_nontemporal:
15648 case OMPC_severity:
15650 case OMPC_inclusive:
15651 case OMPC_exclusive:
15652 case OMPC_uses_allocators:
15653 case OMPC_affinity:
15656 case OMPC_num_teams:
15657 case OMPC_thread_limit:
15659 llvm_unreachable(
"Clause is not allowed.");
15672 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15673 "Invalid directive with CKind-clause");
15676 if (NameModifier != OMPD_unknown &&
15677 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15678 return OMPD_unknown;
15697 case OMPD_teams_loop:
15698 case OMPD_target_teams_loop:
15702 case OMPD_target_update:
15703 case OMPD_target_enter_data:
15704 case OMPD_target_exit_data:
15710 case OMPC_num_teams:
15711 case OMPC_thread_limit:
15712 case OMPC_ompx_dyn_cgroup_mem:
15713 if (Leafs[0] == OMPD_target)
15714 return OMPD_target;
15717 if (Leafs[0] == OMPD_target ||
15718 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15719 OMPD_target_enter_data, OMPD_target_exit_data},
15723 case OMPC_novariants:
15724 case OMPC_nocontext:
15725 if (DKind == OMPD_dispatch)
15729 if (DKind == OMPD_metadirective)
15730 return OMPD_metadirective;
15733 return OMPD_unknown;
15746 int InnermostIdx = [&]() {
15747 for (
int I = EndIdx - 1; I >= 0; --I) {
15748 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15756 for (
int I = InnermostIdx - 1; I >= 0; --I) {
15761 if (Regions[0] != OMPD_unknown)
15762 return Regions.back();
15764 return OMPD_unknown;
15769 for (
int I = 0,
E = Leafs.size(); I !=
E; ++I) {
15770 if (Leafs[I] == Dir)
15776 int End = NameModifier == OMPD_unknown ? Leafs.size()
15777 : GetLeafIndex(NameModifier);
15778 return GetEnclosingRegion(End, CKind);
15781 return OMPD_unknown;
15789 Stmt *HelperValStmt =
nullptr;
15792 !
Condition->isInstantiationDependent() &&
15793 !
Condition->containsUnexpandedParameterPack()) {
15798 ValExpr = Val.
get();
15802 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
15803 if (CaptureRegion != OMPD_unknown &&
15806 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15807 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15813 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15814 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15822 Stmt *HelperValStmt =
nullptr;
15825 !
Condition->isInstantiationDependent() &&
15826 !
Condition->containsUnexpandedParameterPack()) {
15836 if (CaptureRegion != OMPD_unknown &&
15839 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15840 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15846 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15857 IntConvertDiagnoser()
15858 : ICEConvertDiagnoser(
false,
false,
true) {}
15861 return S.
Diag(
Loc, diag::err_omp_not_integral) <<
T;
15865 return S.
Diag(
Loc, diag::err_omp_incomplete_type) <<
T;
15870 return S.
Diag(
Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
15879 return S.
Diag(
Loc, diag::err_omp_ambiguous_conversion) <<
T;
15888 llvm_unreachable(
"conversion functions are permitted");
15890 } ConvertDiagnoser;
15896 bool StrictlyPositive,
bool BuildCapture =
false,
15899 Stmt **HelperValStmt =
nullptr) {
15905 if (
Value.isInvalid())
15908 ValExpr =
Value.get();
15910 if (std::optional<llvm::APSInt>
Result =
15912 if (
Result->isSigned() &&
15913 !((!StrictlyPositive &&
Result->isNonNegative()) ||
15914 (StrictlyPositive &&
Result->isStrictlyPositive()))) {
15915 SemaRef.
Diag(
Loc, diag::err_omp_negative_expression_in_clause)
15925 if (*CaptureRegion != OMPD_unknown &&
15928 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15929 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15940 llvm::raw_svector_ostream Out(Buffer);
15941 unsigned Skipped = Exclude.size();
15942 for (
unsigned I =
First; I <
Last; ++I) {
15943 if (llvm::is_contained(Exclude, I)) {
15948 if (I + Skipped + 2 ==
Last)
15950 else if (I + Skipped + 1 !=
Last)
15953 return std::string(Out.str());
15961 "Unexpected num_threads modifier in OpenMP < 60.");
15966 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
15971 Expr *ValExpr = NumThreads;
15972 Stmt *HelperValStmt =
nullptr;
15983 if (CaptureRegion != OMPD_unknown &&
15986 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15987 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15993 StartLoc, LParenLoc, ModifierLoc, EndLoc);
15998 bool SuppressExprDiags) {
16007 if (SuppressExprDiags) {
16011 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
16014 llvm_unreachable(
"Diagnostic suppressed");
16027 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
16028 (!StrictlyPositive && !
Result.isNonNegative())) {
16034 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16035 CKind == OMPC_allocate) &&
16042 if (!
Result.isRepresentableByInt64()) {
16048 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
16050 else if (CKind == OMPC_ordered)
16069 if (
Result.isNonNegative()) {
16073 diag::err_omp_negative_expression_in_clause)
16076 }
else if (
auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
16083 Diag(DeviceNumExpr->
getExprLoc(), diag::err_expected_expression);
16117 DSAStackTy *Stack) {
16118 if (!Stack->getOMPAllocatorHandleT().isNull())
16125 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
16126 <<
"omp_allocator_handle_t";
16131 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16134 bool ErrorFound =
false;
16135 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16136 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
16137 StringRef Allocator =
16138 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16140 auto *VD = dyn_cast_or_null<ValueDecl>(
16160 Stack->setAllocator(AllocatorKind, Res.
get());
16163 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
16164 <<
"omp_allocator_handle_t";
16181 if (Allocator.isInvalid())
16184 Allocator.get(),
DSAStack->getOMPAllocatorHandleT(),
16187 if (Allocator.isInvalid())
16213 Expr *NumForLoops) {
16219 if (NumForLoops && LParenLoc.
isValid()) {
16224 NumForLoops = NumForLoopsResult.
get();
16226 NumForLoops =
nullptr;
16230 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
16231 StartLoc, LParenLoc, EndLoc);
16232 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
16243 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16245 case OMPC_proc_bind:
16247 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16249 case OMPC_atomic_default_mem_order:
16252 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16256 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16260 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16264 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16268 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16270 case OMPC_severity:
16273 LParenLoc, EndLoc);
16277 case OMPC_num_threads:
16281 case OMPC_allocator:
16282 case OMPC_collapse:
16283 case OMPC_schedule:
16285 case OMPC_firstprivate:
16286 case OMPC_lastprivate:
16288 case OMPC_reduction:
16289 case OMPC_task_reduction:
16290 case OMPC_in_reduction:
16294 case OMPC_copyprivate:
16298 case OMPC_mergeable:
16299 case OMPC_threadprivate:
16300 case OMPC_allocate:
16317 case OMPC_num_teams:
16318 case OMPC_thread_limit:
16319 case OMPC_priority:
16320 case OMPC_grainsize:
16322 case OMPC_num_tasks:
16324 case OMPC_dist_schedule:
16325 case OMPC_defaultmap:
16330 case OMPC_use_device_ptr:
16331 case OMPC_use_device_addr:
16332 case OMPC_is_device_ptr:
16333 case OMPC_has_device_addr:
16334 case OMPC_unified_address:
16335 case OMPC_unified_shared_memory:
16336 case OMPC_reverse_offload:
16337 case OMPC_dynamic_allocators:
16338 case OMPC_self_maps:
16339 case OMPC_device_type:
16341 case OMPC_nontemporal:
16343 case OMPC_novariants:
16344 case OMPC_nocontext:
16346 case OMPC_inclusive:
16347 case OMPC_exclusive:
16348 case OMPC_uses_allocators:
16349 case OMPC_affinity:
16353 llvm_unreachable(
"Clause is not allowed.");
16363 if (Kind == OMP_DEFAULT_unknown) {
16364 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16366 unsigned(OMP_DEFAULT_unknown))
16372 case OMP_DEFAULT_none:
16373 DSAStack->setDefaultDSANone(KindKwLoc);
16375 case OMP_DEFAULT_shared:
16376 DSAStack->setDefaultDSAShared(KindKwLoc);
16378 case OMP_DEFAULT_firstprivate:
16379 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
16381 case OMP_DEFAULT_private:
16382 DSAStack->setDefaultDSAPrivate(KindKwLoc);
16385 llvm_unreachable(
"DSA unexpected in OpenMP default clause");
16397 if (Kind == OMP_PROC_BIND_unknown) {
16398 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16400 unsigned(OMP_PROC_BIND_master),
16403 ? OMP_PROC_BIND_primary
16404 : OMP_PROC_BIND_spread) +
16409 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
16410 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16412 unsigned(OMP_PROC_BIND_master),
16414 unsigned(OMP_PROC_BIND_spread) + 1)
16424 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16426 OMPC_atomic_default_mem_order, 0,
16432 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16441 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16448 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16457 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16471 assert(ME &&
"NULL expr in Message clause");
16480 Stmt *HelperValStmt =
nullptr;
16486 DKind == OMPD_unknown ? OMPD_unknown
16489 if (CaptureRegion != OMPD_unknown &&
16492 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16493 ME = tryBuildCapture(
SemaRef, ME, Captures).get();
16501 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16508 if (Kind != OMPC_ORDER_concurrent ||
16513 "OMPC_ORDER_unknown not greater than 0");
16515 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16524 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16530 DSAStack->setRegionHasOrderConcurrent(
true);
16533 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
16534 DSAStack->getCurScope()->setFlags(existingFlags |
16539 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16548 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16550 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16551 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16553 Except.push_back(OMPC_DEPEND_inoutset);
16554 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16561 KindKwLoc, Kind, EndLoc);
16570 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
16580 QualType SizeTy = SizeExpr->getType();
16609 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16610 SizeExpr =
nullptr;
16614 SanitizedSizeExprs);
16621 size_t NumLoops = PermExprs.size();
16623 llvm::append_range(SanitizedPermExprs, PermExprs);
16625 for (
Expr *&PermExpr : SanitizedPermExprs) {
16628 if (!PermExpr || PermExpr->isInstantiationDependent())
16631 llvm::APSInt PermVal;
16634 bool IsValid = PermEvalExpr.
isUsable();
16636 PermExpr = PermEvalExpr.
get();
16638 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16642 diag::err_omp_interchange_permutation_value_range)
16643 << NumLoops << ExprRange;
16647 if (!PermExpr->isInstantiationDependent() && !IsValid)
16648 PermExpr =
nullptr;
16652 EndLoc, SanitizedPermExprs);
16668 FactorExpr, OMPC_partial,
true);
16671 FactorExpr = FactorResult.
get();
16686 LParenLoc, EndLoc);
16696 case OMPC_schedule:
16697 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16698 assert(Argument.size() == NumberOfElements &&
16699 ArgumentLoc.size() == NumberOfElements);
16704 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16705 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16708 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16710 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16713 case OMPC_dist_schedule:
16716 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16718 case OMPC_defaultmap:
16719 enum { Modifier, DefaultmapKind };
16723 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16727 enum { OrderModifier, OrderKind };
16731 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16734 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16737 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16739 case OMPC_grainsize:
16740 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16741 "Modifier for grainsize clause and its location are expected.");
16744 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16746 case OMPC_num_tasks:
16747 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16748 "Modifier for num_tasks clause and its location are expected.");
16751 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16753 case OMPC_num_threads:
16754 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16755 "Modifier for num_threads clause and its location are expected.");
16758 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16764 case OMPC_allocator:
16765 case OMPC_collapse:
16767 case OMPC_proc_bind:
16769 case OMPC_firstprivate:
16770 case OMPC_lastprivate:
16772 case OMPC_reduction:
16773 case OMPC_task_reduction:
16774 case OMPC_in_reduction:
16778 case OMPC_copyprivate:
16782 case OMPC_mergeable:
16783 case OMPC_threadprivate:
16784 case OMPC_allocate:
16801 case OMPC_num_teams:
16802 case OMPC_thread_limit:
16803 case OMPC_priority:
16810 case OMPC_use_device_ptr:
16811 case OMPC_use_device_addr:
16812 case OMPC_is_device_ptr:
16813 case OMPC_has_device_addr:
16814 case OMPC_unified_address:
16815 case OMPC_unified_shared_memory:
16816 case OMPC_reverse_offload:
16817 case OMPC_dynamic_allocators:
16818 case OMPC_atomic_default_mem_order:
16819 case OMPC_self_maps:
16820 case OMPC_device_type:
16822 case OMPC_nontemporal:
16824 case OMPC_severity:
16827 case OMPC_novariants:
16828 case OMPC_nocontext:
16830 case OMPC_inclusive:
16831 case OMPC_exclusive:
16832 case OMPC_uses_allocators:
16833 case OMPC_affinity:
16837 llvm_unreachable(
"Clause is not allowed.");
16848 Excluded.push_back(M2);
16849 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16850 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16851 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16852 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16853 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16876 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16877 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16878 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16879 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16880 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16886 std::string Values;
16896 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16905 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16906 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16907 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16908 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16909 diag::err_omp_schedule_nonmonotonic_static);
16912 Expr *ValExpr = ChunkSize;
16913 Stmt *HelperValStmt =
nullptr;
16924 ValExpr = Val.
get();
16929 if (std::optional<llvm::APSInt>
Result =
16931 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
16932 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16937 DSAStack->getCurrentDirective(), OMPC_schedule,
16941 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16942 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16950 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16967 case OMPC_mergeable:
17015 case OMPC_unified_address:
17018 case OMPC_unified_shared_memory:
17021 case OMPC_reverse_offload:
17024 case OMPC_dynamic_allocators:
17027 case OMPC_self_maps:
17041 case OMPC_ompx_bare:
17046 case OMPC_num_threads:
17050 case OMPC_allocator:
17051 case OMPC_collapse:
17052 case OMPC_schedule:
17054 case OMPC_firstprivate:
17055 case OMPC_lastprivate:
17057 case OMPC_reduction:
17058 case OMPC_task_reduction:
17059 case OMPC_in_reduction:
17063 case OMPC_copyprivate:
17065 case OMPC_proc_bind:
17066 case OMPC_threadprivate:
17067 case OMPC_allocate:
17073 case OMPC_num_teams:
17074 case OMPC_thread_limit:
17075 case OMPC_priority:
17076 case OMPC_grainsize:
17077 case OMPC_num_tasks:
17079 case OMPC_dist_schedule:
17080 case OMPC_defaultmap:
17085 case OMPC_use_device_ptr:
17086 case OMPC_use_device_addr:
17087 case OMPC_is_device_ptr:
17088 case OMPC_has_device_addr:
17089 case OMPC_atomic_default_mem_order:
17090 case OMPC_device_type:
17092 case OMPC_nontemporal:
17095 case OMPC_severity:
17097 case OMPC_novariants:
17098 case OMPC_nocontext:
17100 case OMPC_inclusive:
17101 case OMPC_exclusive:
17102 case OMPC_uses_allocators:
17103 case OMPC_affinity:
17105 case OMPC_ompx_dyn_cgroup_mem:
17107 llvm_unreachable(
"Clause is not allowed.");
17166 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17252 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17254 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
17255 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17256 <<
Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
17269 bool HasInitClause =
false;
17270 bool IsTargetSync =
false;
17274 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
17275 HasInitClause =
true;
17276 if (InitClause->getIsTargetSync())
17277 IsTargetSync =
true;
17278 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
17282 if (DependClause && HasInitClause && !IsTargetSync) {
17283 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17297 if (ClauseKind == OMPC_init) {
17298 auto *
E = cast<OMPInitClause>(
C)->getInteropVar();
17300 }
else if (ClauseKind == OMPC_use) {
17301 auto *
E = cast<OMPUseClause>(
C)->getInteropVar();
17303 }
else if (ClauseKind == OMPC_destroy) {
17304 auto *
E = cast<OMPDestroyClause>(
C)->getInteropVar();
17309 if (!InteropVars.insert(
DeclResult.first).second) {
17310 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17326 Expr *RefExpr = InteropVarExpr;
17329 false,
"omp_interop_t");
17340 bool HasError =
false;
17346 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
17347 InteropType =
QualType(TD->getTypeForDecl(), 0);
17356 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
17357 <<
"omp_interop_t";
17363 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17369 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17371 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
17393 if (isa<StringLiteral>(
E))
17400 StartLoc, LParenLoc, VarLoc, EndLoc);
17413 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17422 DSAStack->getCurrentDirective() == OMPD_depobj) {
17424 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17426 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
17442 Stmt *HelperValStmt =
nullptr;
17445 !
Condition->isInstantiationDependent() &&
17446 !
Condition->containsUnexpandedParameterPack()) {
17456 if (CaptureRegion != OMPD_unknown &&
17459 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17460 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17466 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17474 Stmt *HelperValStmt =
nullptr;
17477 !
Condition->isInstantiationDependent() &&
17478 !
Condition->containsUnexpandedParameterPack()) {
17488 if (CaptureRegion != OMPD_unknown &&
17491 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17492 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17498 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17505 Expr *ValExpr = ThreadID;
17506 Stmt *HelperValStmt =
nullptr;
17511 if (CaptureRegion != OMPD_unknown &&
17514 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17515 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17520 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17531 int ExtraModifier =
Data.ExtraModifier;
17532 int OriginalSharingModifier =
Data.OriginalSharingModifier;
17539 case OMPC_firstprivate:
17542 case OMPC_lastprivate:
17544 "Unexpected lastprivate modifier.");
17547 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17552 case OMPC_reduction:
17554 "Unexpected lastprivate modifier.");
17558 ExtraModifier, OriginalSharingModifier),
17559 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17560 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17562 case OMPC_task_reduction:
17564 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17565 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17567 case OMPC_in_reduction:
17569 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17570 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17574 "Unexpected linear modifier.");
17576 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
17578 ColonLoc,
Data.StepModifierLoc, EndLoc);
17582 LParenLoc, ColonLoc, EndLoc);
17587 case OMPC_copyprivate:
17595 "Unexpected depend modifier.");
17598 ColonLoc,
Data.OmpAllMemoryLoc},
17599 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17603 "Unexpected map modifier.");
17605 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
17606 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
17608 ExtraModifierLoc, ColonLoc, VarList, Locs);
17613 Data.ReductionOrMapperIdScopeSpec,
17614 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17618 Data.ReductionOrMapperIdScopeSpec,
17619 Data.ReductionOrMapperId, ColonLoc, VarList,
17622 case OMPC_use_device_ptr:
17625 case OMPC_use_device_addr:
17628 case OMPC_is_device_ptr:
17631 case OMPC_has_device_addr:
17634 case OMPC_allocate: {
17638 if (!
Data.AllocClauseModifiers.empty()) {
17639 assert(
Data.AllocClauseModifiers.size() <= 2 &&
17640 "More allocate modifiers than expected");
17641 Modifier1 =
Data.AllocClauseModifiers[0];
17642 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
17643 if (
Data.AllocClauseModifiers.size() == 2) {
17644 Modifier2 =
Data.AllocClauseModifiers[1];
17645 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
17649 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
17650 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
17654 case OMPC_nontemporal:
17657 case OMPC_inclusive:
17660 case OMPC_exclusive:
17663 case OMPC_affinity:
17665 Data.DepModOrTailExpr, VarList);
17667 case OMPC_doacross:
17670 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17672 case OMPC_num_teams:
17675 case OMPC_thread_limit:
17681 case OMPC_num_threads:
17685 case OMPC_allocator:
17686 case OMPC_collapse:
17688 case OMPC_proc_bind:
17689 case OMPC_schedule:
17693 case OMPC_mergeable:
17694 case OMPC_threadprivate:
17708 case OMPC_priority:
17709 case OMPC_grainsize:
17711 case OMPC_num_tasks:
17713 case OMPC_dist_schedule:
17714 case OMPC_defaultmap:
17717 case OMPC_unified_address:
17718 case OMPC_unified_shared_memory:
17719 case OMPC_reverse_offload:
17720 case OMPC_dynamic_allocators:
17721 case OMPC_atomic_default_mem_order:
17722 case OMPC_self_maps:
17723 case OMPC_device_type:
17727 case OMPC_severity:
17730 case OMPC_novariants:
17731 case OMPC_nocontext:
17733 case OMPC_uses_allocators:
17737 llvm_unreachable(
"Clause is not allowed.");
17769 bool IsImplicitClause =
17771 for (
Expr *RefExpr : VarList) {
17772 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
17775 Expr *SimpleRefExpr = RefExpr;
17779 Vars.push_back(RefExpr);
17780 PrivateCopies.push_back(
nullptr);
17787 auto *VD = dyn_cast<VarDecl>(
D);
17793 diag::err_omp_private_incomplete_type))
17795 Type =
Type.getNonReferenceType();
17815 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17816 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17817 Diag(ELoc, diag::err_omp_wrong_dsa)
17828 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17830 << getOpenMPDirectiveName(CurrDir, OMPVersion);
17831 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17834 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17849 CurrDir == OMPD_target) {
17851 if (
DSAStack->checkMappableExprComponentListsForDecl(
17855 ConflictKind = WhereFoundClauseKind;
17858 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17861 << getOpenMPDirectiveName(CurrDir, OMPVersion);
17880 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17889 auto *FD = dyn_cast<FieldDecl>(
D);
17893 RefExpr->getExprLoc());
17897 if (!IsImplicitClause)
17898 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17900 ? RefExpr->IgnoreParens()
17902 PrivateCopies.push_back(VDPrivateRefExpr);
17909 Vars, PrivateCopies);
17920 bool IsImplicitClause =
17925 for (
Expr *RefExpr : VarList) {
17926 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
17929 Expr *SimpleRefExpr = RefExpr;
17933 Vars.push_back(RefExpr);
17934 PrivateCopies.push_back(
nullptr);
17935 Inits.push_back(
nullptr);
17941 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17943 auto *VD = dyn_cast<VarDecl>(
D);
17949 diag::err_omp_firstprivate_incomplete_type))
17951 Type =
Type.getNonReferenceType();
17961 DSAStackTy::DSAVarData TopDVar;
17962 if (!IsImplicitClause) {
17963 DSAStackTy::DSAVarData DVar =
17975 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17977 DVar.CKind != OMPC_lastprivate) &&
17979 Diag(ELoc, diag::err_omp_wrong_dsa)
17997 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17998 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17999 Diag(ELoc, diag::err_omp_wrong_dsa)
18025 DVar =
DSAStack->getImplicitDSA(
D,
true);
18026 if (DVar.CKind != OMPC_shared &&
18029 DVar.DKind == OMPD_unknown)) {
18030 Diag(ELoc, diag::err_omp_required_access)
18052 return C == OMPC_reduction && !AppliedToPointee;
18060 if (DVar.CKind == OMPC_reduction &&
18064 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18065 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
18081 CurrDir == OMPD_target) {
18083 if (
DSAStack->checkMappableExprComponentListsForDecl(
18088 ConflictKind = WhereFoundClauseKind;
18091 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18094 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
18105 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18107 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
18109 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
18112 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18121 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
18127 Expr *VDInitRefExpr =
nullptr;
18137 ElemType,
".firstprivate.temp");
18152 ".firstprivate.temp");
18154 RefExpr->getExprLoc());
18160 if (IsImplicitClause) {
18161 Diag(RefExpr->getExprLoc(),
18162 diag::note_omp_task_predetermined_firstprivate_here);
18169 RefExpr->getExprLoc());
18172 if (TopDVar.CKind == OMPC_lastprivate) {
18173 Ref = TopDVar.PrivateCopy;
18175 auto *FD = dyn_cast<FieldDecl>(
D);
18180 RefExpr->getExprLoc());
18184 ExprCaptures.push_back(Ref->
getDecl());
18187 if (!IsImplicitClause)
18188 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18190 ? RefExpr->IgnoreParens()
18192 PrivateCopies.push_back(VDPrivateRefExpr);
18193 Inits.push_back(VDInitRefExpr);
18200 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
18209 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
18210 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18223 for (
Expr *RefExpr : VarList) {
18224 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
18227 Expr *SimpleRefExpr = RefExpr;
18231 Vars.push_back(RefExpr);
18232 SrcExprs.push_back(
nullptr);
18233 DstExprs.push_back(
nullptr);
18234 AssignmentOps.push_back(
nullptr);
18241 auto *VD = dyn_cast<VarDecl>(
D);
18247 diag::err_omp_lastprivate_incomplete_type))
18249 Type =
Type.getNonReferenceType();
18266 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18267 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
18270 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18284 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
18285 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18287 DVar.CKind != OMPC_firstprivate) &&
18288 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
18289 Diag(ELoc, diag::err_omp_wrong_dsa)
18302 DSAStackTy::DSAVarData TopDVar = DVar;
18306 DVar =
DSAStack->getImplicitDSA(
D,
true);
18307 if (DVar.CKind != OMPC_shared) {
18308 Diag(ELoc, diag::err_omp_required_access)
18326 Type.getUnqualifiedType(),
".lastprivate.src",
18337 PseudoDstExpr, PseudoSrcExpr);
18347 if (TopDVar.CKind == OMPC_firstprivate) {
18348 Ref = TopDVar.PrivateCopy;
18352 ExprCaptures.push_back(Ref->
getDecl());
18354 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18362 SimpleRefExpr, RefRes.
get());
18365 ExprPostUpdates.push_back(
18369 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18371 ? RefExpr->IgnoreParens()
18373 SrcExprs.push_back(PseudoSrcExpr);
18374 DstExprs.push_back(PseudoDstExpr);
18375 AssignmentOps.push_back(AssignmentOp.
get());
18382 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
18383 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
18393 for (
Expr *RefExpr : VarList) {
18394 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
18397 Expr *SimpleRefExpr = RefExpr;
18401 Vars.push_back(RefExpr);
18407 auto *VD = dyn_cast<VarDecl>(
D);
18415 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
18416 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18418 Diag(ELoc, diag::err_omp_wrong_dsa)
18429 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18431 ? RefExpr->IgnoreParens()
18443class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
18448 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
18449 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
18450 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18452 if (DVar.CKind != OMPC_unknown)
18454 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18461 return DVarPrivate.CKind != OMPC_unknown;
18465 bool VisitStmt(
Stmt *S) {
18466 for (
Stmt *Child : S->children()) {
18467 if (Child && Visit(Child))
18472 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18479class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
18486 : BaseTransform(SemaRef),
Field(
FieldDecl), CapturedExpr(nullptr) {}
18490 E->getMemberDecl() == Field) {
18492 return CapturedExpr;
18494 return BaseTransform::TransformMemberExpr(
E);
18496 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
18500template <
typename T,
typename U>
18503 for (
U &
Set : Lookups) {
18504 for (
auto *
D :
Set) {
18505 if (
T Res = Gen(cast<ValueDecl>(
D)))
18520 auto ND = cast<NamedDecl>(RD);
18538 AssociatedClasses);
18551 for (
auto *NS : AssociatedNamespaces) {
18564 for (
auto *
D : R) {
18565 auto *Underlying =
D;
18566 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
18567 Underlying = USD->getTargetDecl();
18569 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18570 !isa<OMPDeclareMapperDecl>(Underlying))
18577 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
18578 Underlying = USD->getTargetDecl();
18580 Lookups.emplace_back();
18581 Lookups.back().addDecl(Underlying);
18601 S = S->getParent();
18602 }
while (S && !S->isDeclScope(
D));
18604 S = S->getParent();
18605 Lookups.emplace_back();
18606 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18609 }
else if (
auto *ULE =
18610 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18612 Decl *PrevD =
nullptr;
18616 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(
D))
18617 Lookups.back().addDecl(DRD);
18624 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
18625 return !D->isInvalidDecl() &&
18626 (D->getType()->isDependentType() ||
18627 D->getType()->isInstantiationDependentType() ||
18628 D->getType()->containsUnexpandedParameterPack());
18641 true, ResSet.
begin(), ResSet.
end(),
false,
18664 if (IsComplete || RD->isBeingDefined()) {
18667 if (Lookup.
empty()) {
18668 Lookups.emplace_back();
18669 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18676 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18686 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18711 if (ReductionIdScopeSpec.
isSet()) {
18712 SemaRef.
Diag(
Loc, diag::err_omp_not_resolved_reduction_identifier)
18721struct ReductionData {
18746 unsigned RedModifier = 0;
18748 unsigned OrigSharingModifier = 0;
18751 ReductionData() =
delete;
18753 ReductionData(
unsigned Size,
unsigned Modifier = 0,
unsigned OrgModifier = 0)
18754 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
18755 Vars.reserve(Size);
18756 Privates.reserve(Size);
18757 LHSs.reserve(Size);
18758 RHSs.reserve(Size);
18759 ReductionOps.reserve(Size);
18760 IsPrivateVarReduction.reserve(Size);
18761 if (RedModifier == OMPC_REDUCTION_inscan) {
18762 InscanCopyOps.reserve(Size);
18763 InscanCopyArrayTemps.reserve(Size);
18764 InscanCopyArrayElems.reserve(Size);
18766 TaskgroupDescriptors.reserve(Size);
18767 ExprCaptures.reserve(Size);
18768 ExprPostUpdates.reserve(Size);
18772 void push(
Expr *Item,
Expr *ReductionOp) {
18773 Vars.emplace_back(Item);
18774 Privates.emplace_back(
nullptr);
18775 LHSs.emplace_back(
nullptr);
18776 RHSs.emplace_back(
nullptr);
18777 ReductionOps.emplace_back(ReductionOp);
18778 IsPrivateVarReduction.emplace_back(
false);
18779 TaskgroupDescriptors.emplace_back(
nullptr);
18780 if (RedModifier == OMPC_REDUCTION_inscan) {
18781 InscanCopyOps.push_back(
nullptr);
18782 InscanCopyArrayTemps.push_back(
nullptr);
18783 InscanCopyArrayElems.push_back(
nullptr);
18788 Expr *TaskgroupDescriptor,
Expr *CopyOp,
Expr *CopyArrayTemp,
18789 Expr *CopyArrayElem,
bool IsPrivate) {
18790 Vars.emplace_back(Item);
18791 Privates.emplace_back(Private);
18792 LHSs.emplace_back(LHS);
18793 RHSs.emplace_back(RHS);
18794 ReductionOps.emplace_back(ReductionOp);
18795 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18796 if (RedModifier == OMPC_REDUCTION_inscan) {
18797 InscanCopyOps.push_back(CopyOp);
18798 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18799 InscanCopyArrayElems.push_back(CopyArrayElem);
18801 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
18802 CopyArrayElem ==
nullptr &&
18803 "Copy operation must be used for inscan reductions only.");
18805 IsPrivateVarReduction.emplace_back(IsPrivate);
18814 if (Length ==
nullptr) {
18821 SingleElement =
true;
18822 ArraySizes.push_back(llvm::APSInt::get(1));
18825 if (!Length->EvaluateAsInt(
Result, Context))
18828 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18829 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18830 ArraySizes.push_back(ConstantLengthValue);
18838 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
18839 Length = TempOASE->getLength();
18840 if (Length ==
nullptr) {
18847 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18848 ArraySizes.push_back(ConstantOne);
18851 if (!Length->EvaluateAsInt(
Result, Context))
18854 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18855 if (ConstantLengthValue.getSExtValue() != 1)
18858 ArraySizes.push_back(ConstantLengthValue);
18860 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18864 if (!SingleElement) {
18865 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
18867 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18868 ArraySizes.push_back(ConstantOne);
18869 Base = TempASE->getBase()->IgnoreParenImpCasts();
18881 return BO_AddAssign;
18883 return BO_MulAssign;
18885 return BO_AndAssign;
18887 return BO_OrAssign;
18889 return BO_XorAssign;
18945 case OO_Array_Delete:
18954 case OO_GreaterEqual:
18956 case OO_MinusEqual:
18958 case OO_SlashEqual:
18959 case OO_PercentEqual:
18960 case OO_CaretEqual:
18964 case OO_GreaterGreater:
18965 case OO_LessLessEqual:
18966 case OO_GreaterGreaterEqual:
18967 case OO_EqualEqual:
18968 case OO_ExclaimEqual:
18971 case OO_MinusMinus:
18977 case OO_Conditional:
18980 llvm_unreachable(
"Unexpected reduction identifier");
18983 if (II->isStr(
"max"))
18985 else if (II->isStr(
"min"))
18993 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
18994 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18997 if (ReductionIdScopeSpec.
isValid())
19003 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19004 bool FirstIter =
true;
19005 for (
Expr *RefExpr : VarList) {
19006 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
19014 if (!FirstIter && IR != ER)
19019 bool IsPrivate =
false;
19020 Expr *SimpleRefExpr = RefExpr;
19029 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19030 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
19031 Expr *ReductionOp =
nullptr;
19033 (DeclareReductionRef.
isUnset() ||
19034 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get())))
19035 ReductionOp = DeclareReductionRef.
get();
19037 RD.push(RefExpr, ReductionOp);
19043 Expr *TaskgroupDescriptor =
nullptr;
19045 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19046 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
19048 Type = ASE->getType().getNonReferenceType();
19053 Type = ATy->getElementType();
19056 Type =
Type.getNonReferenceType();
19060 auto *VD = dyn_cast<VarDecl>(
D);
19066 diag::err_omp_reduction_incomplete_type))
19072 false, ASE || OASE))
19079 if (!ASE && !OASE) {
19081 VarDecl *VDDef = VD->getDefinition();
19083 DSARefChecker Check(Stack);
19084 if (Check.Visit(VDDef->
getInit())) {
19085 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19104 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
19105 if (DVar.CKind == OMPC_reduction) {
19106 S.
Diag(ELoc, diag::err_omp_once_referenced)
19109 S.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19112 if (DVar.CKind != OMPC_unknown) {
19113 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
19129 DVar = Stack->getImplicitDSA(
D,
true);
19130 if (DVar.CKind != OMPC_shared) {
19131 S.
Diag(ELoc, diag::err_omp_required_access)
19145 DVar = Stack->getImplicitDSA(
D,
true);
19147 IsPrivate = DVar.CKind != OMPC_shared;
19148 bool IsOrphaned =
false;
19150 IsOrphaned = ParentDir == OMPD_unknown;
19152 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
19158 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
19159 if (DVar.CKind == OMPC_threadprivate) {
19160 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
19172 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19173 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
19177 (DeclareReductionRef.
isUnset() ||
19178 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get()))) {
19179 RD.push(RefExpr, DeclareReductionRef.
get());
19182 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
19186 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19187 <<
Type << ReductionIdRange;
19190 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19191 <<
Type << ReductionIdRange;
19203 if (DeclareReductionRef.
isUnset()) {
19204 if ((BOK == BO_GT || BOK == BO_LT) &&
19207 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19210 if (!ASE && !OASE) {
19211 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19214 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19219 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19221 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19223 if (!ASE && !OASE) {
19224 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19227 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19234 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
19243 bool ConstantLengthOASE =
false;
19245 bool SingleElement;
19248 Context, OASE, SingleElement, ArraySizes);
19251 if (ConstantLengthOASE && !SingleElement) {
19252 for (llvm::APSInt &Size : ArraySizes)
19259 if ((OASE && !ConstantLengthOASE) ||
19261 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19264 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19265 S.
Diag(ELoc, diag::note_vla_unsupported);
19268 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19269 S.
targetDiag(ELoc, diag::note_vla_unsupported);
19282 }
else if (!ASE && !OASE &&
19284 PrivateTy =
D->getType().getNonReferenceType();
19290 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
19295 if (DeclareReductionRef.
isUsable()) {
19297 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19298 if (DRD->getInitializer()) {
19324 Type = ComplexTy->getElementType();
19326 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19333 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19355 llvm::APInt InitValue =
19356 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19357 : llvm::APInt::getMinValue(Size)
19358 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19359 : llvm::APInt::getMaxValue(Size);
19370 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19401 llvm_unreachable(
"Unexpected reduction operation");
19410 }
else if (!
Init) {
19420 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19421 <<
Type << ReductionIdRange;
19422 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19425 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19431 if (DeclareReductionRef.
isUsable()) {
19436 if (!BasePath.empty()) {
19440 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
19443 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
19447 QualType Params[] = {PtrRedTy, PtrRedTy};
19462 CombBOK, LHSDRE, RHSDRE);
19469 if (BOK != BO_LT && BOK != BO_GT) {
19472 BO_Assign, LHSDRE, ReductionOp.
get());
19474 auto *ConditionalOp =
new (Context)
19479 BO_Assign, LHSDRE, ConditionalOp);
19492 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19493 if (ClauseKind == OMPC_reduction &&
19494 RD.RedModifier == OMPC_REDUCTION_inscan) {
19496 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19506 if (Stack->getCurrentDirective() == OMPD_simd ||
19544 if (ClauseKind == OMPC_in_reduction) {
19547 const Expr *ParentReductionOp =
nullptr;
19548 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
19549 DSAStackTy::DSAVarData ParentBOKDSA =
19550 Stack->getTopMostTaskgroupReductionData(
D, ParentSR, ParentBOK,
19552 DSAStackTy::DSAVarData ParentReductionOpDSA =
19553 Stack->getTopMostTaskgroupReductionData(
19554 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19555 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19556 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19557 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
19558 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
19559 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19560 bool EmitError =
true;
19561 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
19562 llvm::FoldingSetNodeID RedId, ParentRedId;
19563 ParentReductionOp->
Profile(ParentRedId, Context,
true);
19564 DeclareReductionRef.
get()->
Profile(RedId, Context,
19566 EmitError = RedId != ParentRedId;
19570 diag::err_omp_reduction_identifier_mismatch)
19571 << ReductionIdRange << RefExpr->getSourceRange();
19573 diag::note_omp_previous_reduction_identifier)
19575 << (IsParentBOK ? ParentBOKDSA.RefExpr
19576 : ParentReductionOpDSA.RefExpr)
19577 ->getSourceRange();
19581 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19588 TransformExprToCaptures RebuildToCapture(S,
D);
19590 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19591 Ref = RebuildToCapture.getCapturedExpr();
19596 RD.ExprCaptures.emplace_back(Ref->
getDecl());
19602 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19607 Stack->getCurrentDirective() == OMPD_taskgroup) {
19608 S.
Diag(RefExpr->getExprLoc(),
19609 diag::err_omp_reduction_non_addressable_expression)
19610 << RefExpr->getSourceRange();
19613 RD.ExprPostUpdates.emplace_back(
19620 unsigned Modifier = RD.RedModifier;
19623 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19624 Modifier = OMPC_REDUCTION_task;
19625 Stack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19627 if (Modifier == OMPC_REDUCTION_task &&
19628 (CurrDir == OMPD_taskgroup ||
19632 if (DeclareReductionRef.
isUsable())
19633 Stack->addTaskgroupReductionData(
D, ReductionIdRange,
19634 DeclareReductionRef.
get());
19636 Stack->addTaskgroupReductionData(
D, ReductionIdRange, BOK);
19638 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
19639 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
19640 TempArrayElem.
get(), IsPrivate);
19642 return RD.Vars.empty();
19658 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19669 if (Modifier == OMPC_REDUCTION_inscan &&
19670 (
DSAStack->getCurrentDirective() != OMPD_for &&
19671 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19672 DSAStack->getCurrentDirective() != OMPD_simd &&
19673 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19674 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19675 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19678 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
19680 StartLoc, LParenLoc, ColonLoc, EndLoc,
19681 ReductionIdScopeSpec, ReductionId,
19682 UnresolvedReductions, RD))
19686 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19689 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19690 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19693 OriginalSharingModifier);
19701 ReductionData RD(VarList.size());
19703 VarList, StartLoc, LParenLoc, ColonLoc,
19704 EndLoc, ReductionIdScopeSpec, ReductionId,
19705 UnresolvedReductions, RD))
19709 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19711 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19721 ReductionData RD(VarList.size());
19723 StartLoc, LParenLoc, ColonLoc, EndLoc,
19724 ReductionIdScopeSpec, ReductionId,
19725 UnresolvedReductions, RD))
19729 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19731 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19740 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19750 const auto *VD = dyn_cast_or_null<VarDecl>(
D);
19753 diag::err_omp_linear_incomplete_type))
19755 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19757 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19761 Type =
Type.getNonReferenceType();
19768 if (!IsDeclareSimd &&
19773 Type =
Type.getUnqualifiedType().getCanonicalType();
19774 const auto *Ty =
Type.getTypePtrOrNull();
19775 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19776 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
19777 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
19779 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19782 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19805 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19807 LinKind = OMPC_LINEAR_val;
19808 for (
Expr *RefExpr : VarList) {
19809 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19812 Expr *SimpleRefExpr = RefExpr;
19816 Vars.push_back(RefExpr);
19817 Privates.push_back(
nullptr);
19818 Inits.push_back(
nullptr);
19825 auto *VD = dyn_cast<VarDecl>(
D);
19831 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
19832 if (DVar.RefExpr) {
19833 Diag(ELoc, diag::err_omp_wrong_dsa)
19842 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19848 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
19857 ExprCaptures.push_back(Ref->
getDecl());
19864 SimpleRefExpr, RefRes.
get());
19867 ExprPostUpdates.push_back(
19872 if (LinKind == OMPC_LINEAR_uval)
19873 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19875 InitExpr = VD ? SimpleRefExpr : Ref;
19881 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19883 ? RefExpr->IgnoreParens()
19885 Privates.push_back(PrivateRef);
19886 Inits.push_back(InitRef);
19892 Expr *StepExpr = Step;
19893 Expr *CalcStepExpr =
nullptr;
19901 StepExpr = Val.
get();
19915 if (std::optional<llvm::APSInt>
Result =
19917 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
19918 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19919 << Vars[0] << (Vars.size() > 1);
19923 CalcStepExpr = CalcStep.
get();
19928 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19929 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19935 Expr *NumIterations,
Sema &SemaRef,
19936 Scope *S, DSAStackTy *Stack) {
19948 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19949 bool HasErrors =
false;
19950 auto CurInit = Clause.
inits().begin();
19951 auto CurPrivate = Clause.
privates().begin();
19956 Expr *SimpleRefExpr = RefExpr;
19957 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19959 if (Res.second || !
D) {
19960 Updates.push_back(
nullptr);
19961 Finals.push_back(
nullptr);
19965 auto &&Info = Stack->isLoopControlVariable(
D);
19972 diag::err_omp_linear_distribute_var_non_loop_iteration);
19973 Updates.push_back(
nullptr);
19974 Finals.push_back(
nullptr);
19978 Expr *InitExpr = *CurInit;
19981 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19983 if (LinKind == OMPC_LINEAR_uval)
19984 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19988 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19995 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20006 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20009 Final = *CurPrivate;
20013 if (!
Update.isUsable() || !Final.isUsable()) {
20014 Updates.push_back(
nullptr);
20015 Finals.push_back(
nullptr);
20016 UsedExprs.push_back(
nullptr);
20019 Updates.push_back(
Update.get());
20020 Finals.push_back(Final.get());
20022 UsedExprs.push_back(SimpleRefExpr);
20028 UsedExprs.push_back(S);
20030 UsedExprs.append(Clause.
varlist_size() + 1 - UsedExprs.size(),
nullptr);
20041 for (
Expr *RefExpr : VarList) {
20042 assert(RefExpr &&
"NULL expr in OpenMP aligned clause.");
20045 Expr *SimpleRefExpr = RefExpr;
20049 Vars.push_back(RefExpr);
20056 auto *VD = dyn_cast<VarDecl>(
D);
20064 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20066 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
20069 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20076 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(
D, SimpleRefExpr)) {
20077 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20079 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20088 .DefaultFunctionArrayConversion(
20089 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20098 if (Alignment !=
nullptr) {
20103 Alignment = AlignResult.
get();
20109 ColonLoc, EndLoc, Vars, Alignment);
20120 for (
Expr *RefExpr : VarList) {
20121 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
20122 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20124 Vars.push_back(RefExpr);
20125 SrcExprs.push_back(
nullptr);
20126 DstExprs.push_back(
nullptr);
20127 AssignmentOps.push_back(
nullptr);
20136 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20137 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20138 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20139 << 0 << RefExpr->getSourceRange();
20143 Decl *
D = DE->getDecl();
20144 auto *VD = cast<VarDecl>(
D);
20149 Vars.push_back(DE);
20150 SrcExprs.push_back(
nullptr);
20151 DstExprs.push_back(
nullptr);
20152 AssignmentOps.push_back(
nullptr);
20158 if (!
DSAStack->isThreadPrivate(VD)) {
20160 Diag(ELoc, diag::err_omp_required_access)
20162 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
20186 PseudoDstExpr, PseudoSrcExpr);
20195 DSAStack->addDSA(VD, DE, OMPC_copyin);
20196 Vars.push_back(DE);
20197 SrcExprs.push_back(PseudoSrcExpr);
20198 DstExprs.push_back(PseudoDstExpr);
20199 AssignmentOps.push_back(AssignmentOp.
get());
20206 Vars, SrcExprs, DstExprs, AssignmentOps);
20217 for (
Expr *RefExpr : VarList) {
20218 assert(RefExpr &&
"NULL expr in OpenMP copyprivate clause.");
20221 Expr *SimpleRefExpr = RefExpr;
20225 Vars.push_back(RefExpr);
20226 SrcExprs.push_back(
nullptr);
20227 DstExprs.push_back(
nullptr);
20228 AssignmentOps.push_back(
nullptr);
20235 auto *VD = dyn_cast<VarDecl>(
D);
20240 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
20241 DSAStackTy::DSAVarData DVar =
20243 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20245 Diag(ELoc, diag::err_omp_wrong_dsa)
20255 if (DVar.CKind == OMPC_unknown) {
20256 DVar =
DSAStack->getImplicitDSA(
D,
false);
20257 if (DVar.CKind == OMPC_shared) {
20258 Diag(ELoc, diag::err_omp_required_access)
20260 <<
"threadprivate or private in the enclosing context";
20270 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20272 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
20274 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
20277 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20298 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20310 VD ? RefExpr->IgnoreParens()
20312 SrcExprs.push_back(PseudoSrcExpr);
20313 DstExprs.push_back(PseudoDstExpr);
20314 AssignmentOps.push_back(AssignmentOp.
get());
20321 EndLoc, Vars, SrcExprs, DstExprs,
20329 if (VarList.empty())
20338 bool Diagnose =
true) {
20339 QualType OMPDependT = Stack->getOMPDependT();
20340 if (!OMPDependT.
isNull())
20346 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
20349 Stack->setOMPDependT(PT.
get());
20370 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20375 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20385struct DoacrossDataInfoTy {
20391 llvm::APSInt TotalDepCount;
20394static DoacrossDataInfoTy
20401 llvm::APSInt DepCounter(32);
20402 llvm::APSInt TotalDepCount(32);
20404 if (
const Expr *OrderedCountExpr =
20405 Stack->getParentOrderedRegionParam().first) {
20406 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
20407 TotalDepCount.setIsUnsigned(
true);
20410 for (
Expr *RefExpr : VarList) {
20411 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
20412 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20414 Vars.push_back(RefExpr);
20421 if (Stack->getParentOrderedRegionParam().first &&
20422 DepCounter >= TotalDepCount) {
20423 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20437 Vars.push_back(RefExpr);
20444 Expr *RHS =
nullptr;
20445 if (
auto *BO = dyn_cast<BinaryOperator>(
SimpleExpr)) {
20447 OOLoc = BO->getOperatorLoc();
20450 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
SimpleExpr)) {
20451 OOK = OCE->getOperator();
20452 OOLoc = OCE->getOperatorLoc();
20455 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
SimpleExpr)) {
20456 OOK = MCE->getMethodDecl()
20459 .getCXXOverloadedOperator();
20460 OOLoc = MCE->getCallee()->getExprLoc();
20469 Vars.push_back(RefExpr);
20475 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
20476 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20482 RHS, OMPC_depend,
false);
20487 Stack->getParentOrderedRegionParam().first &&
20488 DepCounter != Stack->isParentLoopControlVariable(
D).first) {
20490 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20492 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20495 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20499 OpsOffs.emplace_back(RHS, OOK);
20501 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20504 TotalDepCount > VarList.size() &&
20505 Stack->getParentOrderedRegionParam().first &&
20506 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
20507 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20508 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20510 return {Vars, OpsOffs, TotalDepCount};
20519 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
20520 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20521 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20525 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
20526 DepKind == OMPC_DEPEND_mutexinoutset) {
20527 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20530 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
20531 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20533 DepKind == OMPC_DEPEND_sink ||
20535 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20536 DepKind == OMPC_DEPEND_depobj))) {
20538 OMPC_DEPEND_outallmemory,
20539 OMPC_DEPEND_inoutallmemory};
20541 DSAStack->getCurrentDirective() == OMPD_depobj)
20542 Except.push_back(OMPC_DEPEND_depobj);
20544 Except.push_back(OMPC_DEPEND_inoutset);
20546 ?
"depend modifier(iterator) or "
20548 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20556 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20558 diag::err_omp_depend_sink_source_with_modifier);
20563 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20567 llvm::APSInt TotalDepCount(32);
20569 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20572 Vars = VarOffset.Vars;
20573 OpsOffs = VarOffset.OpsOffs;
20574 TotalDepCount = VarOffset.TotalDepCount;
20576 for (
Expr *RefExpr : VarList) {
20577 assert(RefExpr &&
"NULL expr in OpenMP depend clause.");
20578 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20580 Vars.push_back(RefExpr);
20586 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20587 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
20588 if (OMPDependTFound)
20590 DepKind == OMPC_DEPEND_depobj);
20591 if (DepKind == OMPC_DEPEND_depobj) {
20595 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20596 !RefExpr->isInstantiationDependent() &&
20597 !RefExpr->containsUnexpandedParameterPack() &&
20598 (OMPDependTFound &&
20600 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20601 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20602 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20605 if (!RefExpr->isLValue()) {
20606 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20607 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20614 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20615 const auto *OASE = dyn_cast<ArraySectionExpr>(
SimpleExpr);
20622 ExprTy = ATy->getElementType();
20628 const Expr *Length = OASE->getLength();
20630 if (Length && !Length->isValueDependent() &&
20632 Result.Val.getInt().isZero()) {
20634 diag::err_omp_depend_zero_length_array_section_not_allowed)
20644 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20645 !RefExpr->isInstantiationDependent() &&
20646 !RefExpr->containsUnexpandedParameterPack() &&
20647 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20648 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
20650 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20653 << RefExpr->getSourceRange();
20657 auto *ASE = dyn_cast<ArraySubscriptExpr>(
SimpleExpr);
20658 if (ASE && !ASE->getBase()->isTypeDependent() &&
20661 .getNonReferenceType()
20662 ->isPointerType() &&
20663 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20664 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20667 << RefExpr->getSourceRange();
20675 RefExpr->IgnoreParenImpCasts());
20679 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20682 << RefExpr->getSourceRange();
20687 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20691 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20692 DepKind != OMPC_DEPEND_outallmemory &&
20693 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20698 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
20699 TotalDepCount.getZExtValue());
20700 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20701 DSAStack->isParentOrderedRegion())
20702 DSAStack->addDoacrossDependClause(
C, OpsOffs);
20711 "Unexpected device modifier in OpenMP < 50.");
20713 bool ErrorFound =
false;
20715 std::string Values =
20717 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20723 Stmt *HelperValStmt =
nullptr;
20736 if (Modifier == OMPC_DEVICE_ancestor) {
20740 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20748 if (CaptureRegion != OMPD_unknown &&
20751 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20752 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20757 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20758 LParenLoc, ModifierLoc, EndLoc);
20763 bool FullCheck =
true) {
20768 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20778 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20783 if (isa<ArraySubscriptExpr>(
E) ||
20784 (OASE && OASE->getColonLocFirst().isInvalid())) {
20785 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20786 return ATy->getSExtSize() != 1;
20791 assert(OASE &&
"Expecting array section if not an array subscript.");
20792 const Expr *LowerBound = OASE->getLowerBound();
20793 const Expr *Length = OASE->getLength();
20802 llvm::APSInt ConstLowerBound =
Result.Val.getInt();
20803 if (ConstLowerBound.getSExtValue())
20818 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
20826 llvm::APSInt ConstLength =
Result.Val.getInt();
20827 return CATy->getSExtSize() != ConstLength.getSExtValue();
20836 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20840 if (isa<ArraySubscriptExpr>(
E) ||
20841 (OASE && OASE->getColonLocFirst().isInvalid()))
20844 assert(OASE &&
"Expecting array section if not an array subscript.");
20845 const Expr *Length = OASE->getLength();
20851 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20852 return ATy->getSExtSize() != 1;
20862 llvm::APSInt ConstLength =
Result.Val.getInt();
20863 return ConstLength.getSExtValue() != 1;
20902class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
20907 bool IsNonContiguous =
false;
20908 bool NoDiagnose =
false;
20909 const Expr *RelevantExpr =
nullptr;
20910 bool AllowUnitySizeArraySection =
true;
20911 bool AllowWholeSizeArraySection =
true;
20912 bool AllowAnotherPtr =
true;
20916 void emitErrorMsg() {
20918 if (SemaRef.getLangOpts().OpenMP < 50) {
20920 diag::err_omp_expected_named_var_member_or_array_expression)
20923 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20930 if (!isa<VarDecl>(DRE->
getDecl())) {
20934 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20935 RelevantExpr = DRE;
20937 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
20945 if (isa<CXXThisExpr>(BaseE)) {
20946 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20955 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20971 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20991 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20995 return RelevantExpr || Visit(
E);
21005 AllowUnitySizeArraySection =
false;
21006 AllowWholeSizeArraySection =
false;
21009 Components.emplace_back(ME, FD, IsNonContiguous);
21010 return RelevantExpr || Visit(
E);
21018 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21022 return RelevantExpr || Visit(
E);
21029 AllowWholeSizeArraySection =
false;
21035 !Result.Val.getInt().isZero()) {
21037 diag::err_omp_invalid_map_this_expr);
21039 diag::note_omp_invalid_subscript_on_this_ptr_map);
21041 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21046 Components.emplace_back(AE,
nullptr, IsNonContiguous);
21048 return RelevantExpr || Visit(
E);
21054 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21055 "Array sections cannot be implicitly mapped.");
21069 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21079 if (AllowWholeSizeArraySection) {
21086 if (NotWhole || IsPointer)
21087 AllowWholeSizeArraySection =
false;
21088 }
else if (DKind == OMPD_target_update &&
21089 SemaRef.getLangOpts().OpenMP >= 50) {
21090 if (IsPointer && !AllowAnotherPtr)
21091 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21094 IsNonContiguous =
true;
21095 }
else if (AllowUnitySizeArraySection && NotUnity) {
21101 diag::err_array_section_does_not_specify_contiguous_storage)
21107 AllowAnotherPtr =
false;
21109 if (
const auto *TE = dyn_cast<CXXThisExpr>(
E)) {
21116 diag::err_omp_invalid_map_this_expr);
21118 diag::note_omp_invalid_length_on_this_ptr_mapping);
21122 SemaRef.getASTContext()) &&
21125 diag::err_omp_invalid_map_this_expr);
21127 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21129 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21134 Components.emplace_back(OASE,
nullptr,
false);
21135 return RelevantExpr || Visit(
E);
21141 Components.emplace_back(
E,
nullptr, IsNonContiguous);
21143 return Visit(
Base->IgnoreParenImpCasts());
21147 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
21152 if (!RelevantExpr) {
21154 Components.emplace_back(UO,
nullptr,
false);
21170 Components.emplace_back(BO,
nullptr,
false);
21173 "Either LHS or RHS have base decl inside");
21175 return RelevantExpr || Visit(LE);
21176 return RelevantExpr || Visit(RE);
21179 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21180 RelevantExpr = CTE;
21181 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
21185 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
21186 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
21190 Expr *Source =
E->getSourceExpr();
21195 return Visit(Source);
21197 bool VisitStmt(
Stmt *) {
21201 const Expr *getFoundBase()
const {
return RelevantExpr; }
21202 explicit MapBaseChecker(
21206 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21207 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21221 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21225 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21226 (CKind == OMPC_to || CKind == OMPC_from)) {
21227 auto CI = CurComponents.rbegin();
21228 auto CE = CurComponents.rend();
21229 for (; CI != CE; ++CI) {
21231 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
21236 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
21240 return Checker.getFoundBase();
21249 bool CurrentRegionOnly,
21260 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
21261 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21262 "Map clause expression with unexpected base!");
21265 bool IsEnclosedByDataEnvironmentExpr =
false;
21266 const Expr *EnclosingExpr =
nullptr;
21268 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21269 VD, CurrentRegionOnly,
21270 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21271 ERange, CKind, &EnclosingExpr,
21275 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
21277 assert(!StackComponents.empty() &&
21278 "Map clause expression with no components!");
21279 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21280 "Map clause expression with unexpected base!");
21284 const Expr *RE = StackComponents.front().getAssociatedExpression();
21290 auto CI = CurComponents.rbegin();
21291 auto CE = CurComponents.rend();
21292 auto SI = StackComponents.rbegin();
21293 auto SE = StackComponents.rend();
21294 for (; CI != CE && SI != SE; ++CI, ++SI) {
21299 if (CurrentRegionOnly &&
21300 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21301 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
21302 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21303 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21304 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
21305 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21306 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21307 diag::err_omp_multiple_array_items_in_map_clause)
21308 << CI->getAssociatedExpression()->getSourceRange();
21309 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21310 diag::note_used_here)
21311 << SI->getAssociatedExpression()->getSourceRange();
21316 if (CI->getAssociatedExpression()->getStmtClass() !=
21317 SI->getAssociatedExpression()->getStmtClass())
21321 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21327 for (; SI != SE; ++SI) {
21329 if (
const auto *ASE =
21330 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21331 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21332 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
21333 SI->getAssociatedExpression())) {
21334 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21335 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21336 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21337 SI->getAssociatedExpression())) {
21338 Type = OASE->getBase()->getType()->getPointeeType();
21342 SemaRef, SI->getAssociatedExpression(),
Type))
21352 if (CI == CE && SI == SE) {
21353 if (CurrentRegionOnly) {
21354 if (CKind == OMPC_map) {
21355 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21357 assert(CKind == OMPC_to || CKind == OMPC_from);
21358 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21367 IsEnclosedByDataEnvironmentExpr =
true;
21372 std::prev(CI)->getAssociatedDeclaration()->getType();
21374 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21393 if (CI == CE || SI == SE) {
21396 diag::err_omp_pointer_mapped_along_with_derived_section)
21402 if (CI->getAssociatedExpression()->getStmtClass() !=
21403 SI->getAssociatedExpression()->getStmtClass() ||
21404 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21405 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21406 assert(CI != CE && SI != SE);
21407 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21420 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21421 if (CKind == OMPC_map) {
21422 if (CI != CE || SI != SE) {
21426 CI != CE ? CurComponents.begin() : StackComponents.begin();
21427 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21429 while (It != End && !It->getAssociatedDeclaration())
21430 std::advance(It, 1);
21431 assert(It != End &&
21432 "Expected at least one component with the declaration.");
21433 if (It !=
Begin && It->getAssociatedDeclaration()
21435 .getCanonicalType()
21436 ->isAnyPointerType()) {
21437 IsEnclosedByDataEnvironmentExpr =
false;
21438 EnclosingExpr =
nullptr;
21442 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21444 assert(CKind == OMPC_to || CKind == OMPC_from);
21445 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21455 if (!CurrentRegionOnly && SI != SE)
21456 EnclosingExpr = RE;
21460 IsEnclosedByDataEnvironmentExpr |=
21461 (!CurrentRegionOnly && CI != CE && SI == SE);
21466 if (CurrentRegionOnly)
21480 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21482 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21498 Expr *UnresolvedMapper) {
21514 while (S && !S->isDeclScope(
D))
21515 S = S->getParent();
21517 S = S->getParent();
21518 Lookups.emplace_back();
21519 Lookups.back().append(Lookup.
begin(), Lookup.
end());
21522 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21526 auto *DMD = cast<OMPDeclareMapperDecl>(
D);
21527 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
21528 Lookups.back().addDecl(DMD);
21536 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
21537 return !D->isInvalidDecl() &&
21538 (D->getType()->isDependentType() ||
21539 D->getType()->isInstantiationDependentType() ||
21540 D->getType()->containsUnexpandedParameterPack());
21551 false, URS.
begin(), URS.
end(),
false,
21559 SemaRef.
Diag(
Loc, diag::err_omp_mapper_wrong_type);
21566 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21576 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21580 !
Type.isMoreQualifiedThan(
D->getType(),
21600 SemaRef.
Diag(
Loc, diag::err_omp_invalid_mapper)
21610struct MappableVarListInfo {
21625 VarComponents.reserve(VarList.size());
21626 VarBaseDeclarations.reserve(VarList.size());
21645 for (
auto *FD : RD->
fields()) {
21653 SExprs.push_back(BE);
21661 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21664 Maps.push_back(MapClause);
21665 return MapperVarRef;
21669 DSAStackTy *Stack) {
21684 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
21686 BaseType, MapperId, Maps,
nullptr);
21692 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21696 DMD->setMapperVarRef(MapperVarRef);
21716 while (S && !S->isDeclScope(
D))
21717 S = S->getParent();
21719 S = S->getParent();
21720 Lookups.emplace_back();
21721 Lookups.back().append(Lookup.
begin(), Lookup.
end());
21727 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
21728 return !D->isInvalidDecl() &&
21729 (D->getType()->isDependentType() ||
21730 D->getType()->isInstantiationDependentType() ||
21731 D->getType()->containsUnexpandedParameterPack());
21738 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21748 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21761 bool IsAmbiguous = !Paths.isAmbiguous(
21777 {CanonType,
nullptr});
21778 llvm::DenseMap<const Type *, bool>
Visited;
21780 while (!Types.empty()) {
21781 auto [BaseType, CurFD] = Types.pop_back_val();
21782 while (ParentChain.back().second == 0)
21783 ParentChain.pop_back();
21784 --ParentChain.back().second;
21785 if (BaseType.isNull())
21788 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21791 auto It =
Visited.find(BaseType.getTypePtr());
21801 DefaultMapperId, BaseType);
21802 It =
Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21808 bool FirstIter =
true;
21818 ParentChain.emplace_back(CurFD, 1);
21820 ++ParentChain.back().second;
21822 Types.emplace_back(FieldTy, FD);
21841 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
21843 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21844 "Unexpected clause kind with mappable expressions!");
21845 unsigned OMPVersion = SemaRef.
getLangOpts().OpenMP;
21853 MapperId.
setName(DeclNames.getIdentifier(
21855 MapperId.
setLoc(StartLoc);
21859 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21860 bool UpdateUMIt =
false;
21861 Expr *UnresolvedMapper =
nullptr;
21863 bool HasHoldModifier =
21864 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21872 for (
Expr *RE : MVLI.VarList) {
21873 assert(RE &&
"Null expr in omp to/from/map clause");
21877 if (UpdateUMIt && UMIt != UMEnd) {
21881 "Expect the size of UnresolvedMappers to match with that of VarList");
21885 UnresolvedMapper = *UMIt;
21894 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21898 MVLI.UDMapperList.push_back(ER.
get());
21901 MVLI.ProcessedVarList.push_back(RE);
21910 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21913 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21926 DSAS->getCurrentDirective(), NoDiagnose);
21930 assert(!CurComponents.empty() &&
21931 "Invalid mappable expression information.");
21933 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21935 DSAS->addMappedClassesQualTypes(TE->getType());
21938 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21942 MVLI.UDMapperList.push_back(ER.
get());
21944 MVLI.ProcessedVarList.push_back(RE);
21945 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21946 MVLI.VarComponents.back().append(CurComponents.begin(),
21947 CurComponents.end());
21948 MVLI.VarBaseDeclarations.push_back(
nullptr);
21955 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21956 assert(CurDeclaration &&
"Null decl on map clause.");
21959 "Expecting components to have associated only canonical declarations.");
21961 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21962 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21964 assert((VD || FD) &&
"Only variables or fields are expected here!");
21971 if (VD && DSAS->isThreadPrivate(VD)) {
21974 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21975 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21990 true, CurComponents, CKind))
21992 if (CKind == OMPC_map &&
21995 false, CurComponents, CKind))
22002 auto I = llvm::find_if(
22007 assert(I != CurComponents.end() &&
"Null decl on map clause.");
22010 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->
IgnoreParens());
22011 auto *OASE = dyn_cast<ArraySectionExpr>(VE->
IgnoreParens());
22012 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->
IgnoreParens());
22014 Type = ASE->getType().getNonReferenceType();
22019 Type = ATy->getElementType();
22022 Type =
Type.getNonReferenceType();
22023 }
else if (OAShE) {
22037 if (CKind == OMPC_map) {
22044 if (DKind == OMPD_target_enter_data &&
22045 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22047 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22048 << (IsMapTypeImplicit ? 1 : 0)
22050 << getOpenMPDirectiveName(DKind, OMPVersion);
22059 if (DKind == OMPD_target_exit_data &&
22060 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22061 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
22062 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22063 << (IsMapTypeImplicit ? 1 : 0)
22065 << getOpenMPDirectiveName(DKind, OMPVersion);
22074 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22076 SemaRef.
Diag(StartLoc,
22077 diag::err_omp_invalid_map_type_modifier_for_directive)
22079 OMPC_MAP_MODIFIER_ompx_hold)
22080 << getOpenMPDirectiveName(DKind, OMPVersion);
22088 if ((DKind == OMPD_target_data ||
22090 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22091 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22092 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22093 << (IsMapTypeImplicit ? 1 : 0)
22095 << getOpenMPDirectiveName(DKind, OMPVersion);
22107 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
22109 DKind == OMPD_target)) {
22110 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
22112 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22115 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
22125 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22126 Type.getCanonicalType(), UnresolvedMapper);
22137 if (isa<ArraySectionExpr>(VE)) {
22145 ElemType = ATy->getElementType();
22161 MVLI.UDMapperList.push_back(ER.
get());
22164 MVLI.ProcessedVarList.push_back(RE);
22168 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22174 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22175 MVLI.VarComponents.back().append(CurComponents.begin(),
22176 CurComponents.end());
22177 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ?
nullptr
22198 BuiltinType::OMPIterator))
22200 diag::err_omp_map_modifier_not_iterator);
22203 unsigned Count = 0;
22204 for (
unsigned I = 0,
E = MapTypeModifiers.size(); I <
E; ++I) {
22206 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22207 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22211 "Modifiers exceed the allowed number of map type modifiers");
22212 Modifiers[Count] = MapTypeModifiers[I];
22213 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22217 MappableVarListInfo MVLI(VarList);
22219 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22220 MapType, Modifiers, IsMapTypeImplicit,
22226 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22227 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22229 MapperId, MapType, IsMapTypeImplicit, MapLoc);
22237 if (ReductionType.
isNull())
22245 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22250 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22254 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22258 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22261 return ReductionType;
22267 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22270 Decls.reserve(ReductionTypes.size());
22279 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22281 bool InCompoundScope =
true;
22282 if (S !=
nullptr) {
22291 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22293 while (Filter.hasNext()) {
22294 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22295 if (InCompoundScope) {
22296 UsedAsPrevious.try_emplace(PrevDecl,
false);
22298 UsedAsPrevious[
D] =
true;
22300 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22301 PrevDecl->getLocation();
22304 if (InCompoundScope) {
22305 for (
const auto &PrevData : UsedAsPrevious) {
22306 if (!PrevData.second) {
22307 PrevDRD = PrevData.first;
22312 }
else if (PrevDeclInScope !=
nullptr) {
22313 auto *PrevDRDInScope = PrevDRD =
22314 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22316 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22317 PrevDRDInScope->getLocation();
22318 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22319 }
while (PrevDRDInScope !=
nullptr);
22321 for (
const auto &TyData : ReductionTypes) {
22322 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22324 if (I != PreviousRedeclTypes.end()) {
22325 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22327 Diag(I->second, diag::note_previous_definition);
22330 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22332 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
22334 DRD->setAccess(AS);
22335 Decls.push_back(DRD);
22337 DRD->setInvalidDecl();
22347 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
22362 QualType ReductionType = DRD->getType();
22379 if (S !=
nullptr) {
22383 DRD->addDecl(OmpInParm);
22384 DRD->addDecl(OmpOutParm);
22390 DRD->setCombinerData(InE, OutE);
22395 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
22402 if (Combiner !=
nullptr)
22403 DRD->setCombiner(Combiner);
22405 DRD->setInvalidDecl();
22410 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
22424 QualType ReductionType = DRD->getType();
22441 if (S !=
nullptr) {
22445 DRD->addDecl(OmpPrivParm);
22446 DRD->addDecl(OmpOrigParm);
22452 DRD->setInitializerData(OrigE, PrivE);
22453 return OmpPrivParm;
22458 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
22467 }
else if (OmpPrivParm->
hasInit()) {
22468 DRD->setInitializer(OmpPrivParm->
getInit(),
22473 DRD->setInvalidDecl();
22479 for (
Decl *
D : DeclReductions.
get()) {
22488 return DeclReductions;
22495 if (
D.isInvalidType())
22508 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
22511 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
22516 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22533 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22535 bool InCompoundScope =
true;
22536 if (S !=
nullptr) {
22545 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22547 while (Filter.hasNext()) {
22548 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22549 if (InCompoundScope) {
22550 UsedAsPrevious.try_emplace(PrevDecl,
false);
22552 UsedAsPrevious[
D] =
true;
22554 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22555 PrevDecl->getLocation();
22558 if (InCompoundScope) {
22559 for (
const auto &PrevData : UsedAsPrevious) {
22560 if (!PrevData.second) {
22561 PrevDMD = PrevData.first;
22566 }
else if (PrevDeclInScope) {
22567 auto *PrevDMDInScope = PrevDMD =
22568 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22570 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22571 PrevDMDInScope->getLocation();
22572 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22573 }
while (PrevDMDInScope !=
nullptr);
22577 if (I != PreviousRedeclTypes.end()) {
22578 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22579 << MapperType << Name;
22580 Diag(I->second, diag::note_previous_definition);
22588 ClausesWithImplicit);
22590 MapperType, VN, ClausesWithImplicit,
22596 DMD->setAccess(AS);
22598 DMD->setInvalidDecl();
22600 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22604 DMD->setMapperVarRef(MapperVarRef);
22625 if (
DSAStack->getDeclareMapperVarRef())
22630 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22632 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22645 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22646 return cast<DeclRefExpr>(
DSAStack->getDeclareMapperVarRef())->getDecl();
22653 if (VarList.empty())
22656 for (
Expr *ValExpr : VarList) {
22669 LParenLoc, EndLoc, VarList,
22672 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22674 for (
Expr *ValExpr : VarList) {
22676 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22677 Vars.push_back(ValExpr);
22682 LParenLoc, EndLoc, Vars, PreInit);
22689 if (VarList.empty())
22692 for (
Expr *ValExpr : VarList) {
22705 StartLoc, LParenLoc, EndLoc, VarList,
22708 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22710 for (
Expr *ValExpr : VarList) {
22712 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22713 Vars.push_back(ValExpr);
22718 LParenLoc, EndLoc, Vars, PreInit);
22726 Stmt *HelperValStmt =
nullptr;
22732 ValExpr,
SemaRef, OMPC_priority,
22734 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22738 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22746 "Unexpected grainsize modifier in OpenMP < 51.");
22751 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22756 Expr *ValExpr = Grainsize;
22757 Stmt *HelperValStmt =
nullptr;
22767 &CaptureRegion, &HelperValStmt))
22772 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22780 "Unexpected num_tasks modifier in OpenMP < 51.");
22785 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22790 Expr *ValExpr = NumTasks;
22791 Stmt *HelperValStmt =
nullptr;
22798 ValExpr,
SemaRef, OMPC_num_tasks,
22800 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22805 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22825 DSAStackTy *Stack) {
22826 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22827 if (!OMPEventHandleT.
isNull())
22832 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
22835 Stack->setOMPEventHandleT(PT.
get());
22856 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
22866 <<
"omp_event_handle_t" << 1 << VD->
getType()
22873 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
22874 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22893 std::string Values;
22897 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22901 Expr *ValExpr = ChunkSize;
22902 Stmt *HelperValStmt =
nullptr;
22913 ValExpr = Val.
get();
22918 if (std::optional<llvm::APSInt>
Result =
22920 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
22921 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22922 <<
"dist_schedule" << 1
22927 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22931 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22932 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22940 Kind, ValExpr, HelperValStmt);
22948 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22949 Kind != OMPC_DEFAULTMAP_scalar) {
22953 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22955 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22959 OMPC_DEFAULTMAP_scalar);
22963 Diag(
Loc, diag::err_omp_unexpected_clause_value)
22971 if (!isDefaultmapKind || !isDefaultmapModifier) {
22973 ?
"'scalar', 'aggregate', 'pointer'"
22974 :
"'scalar', 'aggregate', 'pointer', 'all'";
22976 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
22977 "'firstprivate', 'none', 'default'";
22978 if (!isDefaultmapKind && isDefaultmapModifier) {
22979 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22981 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22982 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22985 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22987 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22991 StringRef ModifierValue =
22992 "'alloc', 'from', 'to', 'tofrom', "
22993 "'firstprivate', 'none', 'default', 'present'";
22994 if (!isDefaultmapKind && isDefaultmapModifier) {
22995 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22997 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22998 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23001 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23003 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23013 if (
DSAStack->checkDefaultmapCategory(Kind)) {
23014 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23020 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23021 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23022 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23024 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23037 !isa<CXXRecordDecl>(CurLexicalContext) &&
23038 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23039 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23040 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23041 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
23047 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
23049 DeclareTargetNesting.push_back(DTCI);
23055 assert(!DeclareTargetNesting.empty() &&
23056 "check isInOpenMPDeclareTargetContext() first!");
23057 return DeclareTargetNesting.pop_back_val();
23067 if (DeclareTargetNesting.empty())
23071 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
23072 << getOpenMPDirectiveName(DTCI.
Kind, OMPVersion);
23087 VarOrFuncDeclFilterCCC CCC(
SemaRef);
23098 Diag(
Id.getLoc(), diag::err_undeclared_var_use) <<
Id.getName();
23103 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23104 !isa<FunctionTemplateDecl>(ND)) {
23105 Diag(
Id.getLoc(), diag::err_omp_invalid_target_decl) <<
Id.getName();
23114 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23115 isa<FunctionTemplateDecl>(ND)) &&
23116 "Expected variable, function or function template.");
23118 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
23120 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23121 !VD->isStaticDataMember()) {
23122 Diag(
Loc, diag::err_omp_declare_target_has_local_vars)
23131 Diag(
Loc, diag::warn_omp_declare_target_after_first_use);
23135 Diag(
Loc, diag::warn_hip_omp_target_directives);
23138 const unsigned Level = -1;
23140 auto *VD = cast<ValueDecl>(ND);
23141 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23142 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23143 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
23144 (*ActiveAttr)->getLevel() == Level) {
23145 Diag(
Loc, diag::err_omp_device_type_mismatch)
23146 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
23147 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23148 (*ActiveAttr)->getDevType());
23151 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23152 (*ActiveAttr)->getLevel() == Level) {
23153 Diag(
Loc, diag::err_omp_declare_target_to_and_link) << ND;
23157 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23160 Expr *IndirectE =
nullptr;
23161 bool IsIndirect =
false;
23167 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23172 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23174 if (
auto *VD = dyn_cast<VarDecl>(ND);
23176 VD->hasGlobalStorage())
23182 if (!
D || !isa<VarDecl>(
D))
23184 auto *VD = cast<VarDecl>(
D);
23185 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
23186 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23187 if (SemaRef.
LangOpts.OpenMP >= 50 &&
23190 VD->hasGlobalStorage()) {
23191 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23192 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23199 diag::err_omp_lambda_capture_in_declare_target_not_to);
23200 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
23207 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
23208 SemaRef.
Diag(SL, diag::note_used_here) << SR;
23212 Sema &SemaRef, DSAStackTy *Stack,
23214 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23225 if (
auto *VD = dyn_cast<VarDecl>(
D)) {
23227 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23228 !VD->isStaticDataMember())
23232 if (
DSAStack->isThreadPrivate(VD)) {
23233 Diag(SL, diag::err_omp_threadprivate_in_target);
23238 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(
D))
23239 D = FTD->getTemplatedDecl();
23240 if (
auto *FD = dyn_cast<FunctionDecl>(
D)) {
23241 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23242 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23243 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23244 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23249 if (
auto *VD = dyn_cast<ValueDecl>(
D)) {
23257 if (isa<VarDecl>(
D) || isa<FunctionDecl>(
D) ||
23258 isa<FunctionTemplateDecl>(
D)) {
23259 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23260 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23261 unsigned Level = DeclareTargetNesting.size();
23262 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23265 Expr *IndirectE =
nullptr;
23266 bool IsIndirect =
false;
23272 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23274 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23275 : OMPDeclareTargetDeclAttr::MT_To,
23276 DTCI.
DT, IndirectE, IsIndirect, Level,
23280 ML->DeclarationMarkedOpenMPDeclareTarget(
D, A);
23300 if (
auto *VD = dyn_cast<VarDecl>(
Node->getDecl())) {
23302 DeclVector.push_back(VD);
23307 for (
auto *Child : Ex->
children()) {
23316 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
23317 DeclVector.push_back(cast<VarDecl>(TD));
23318 llvm::SmallDenseSet<Decl *>
Visited;
23319 while (!DeclVector.empty()) {
23320 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23321 if (!
Visited.insert(TargetVarDecl).second)
23324 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
23338 if (isa<VarDecl>(TargetDecl))
23353 unsigned Count = 0;
23354 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
23356 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23357 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23361 "Modifiers exceed the allowed number of motion modifiers");
23362 Modifiers[Count] = MotionModifiers[I];
23363 ModifiersLoc[Count] = MotionModifiersLoc[I];
23367 MappableVarListInfo MVLI(VarList);
23369 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23370 if (MVLI.ProcessedVarList.empty())
23374 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23375 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23390 unsigned Count = 0;
23391 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
23393 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23394 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23398 "Modifiers exceed the allowed number of motion modifiers");
23399 Modifiers[Count] = MotionModifiers[I];
23400 ModifiersLoc[Count] = MotionModifiersLoc[I];
23404 MappableVarListInfo MVLI(VarList);
23406 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23407 if (MVLI.ProcessedVarList.empty())
23411 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23412 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23419 MappableVarListInfo MVLI(VarList);
23423 for (
Expr *RefExpr : VarList) {
23424 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
23427 Expr *SimpleRefExpr = RefExpr;
23431 MVLI.ProcessedVarList.push_back(RefExpr);
23432 PrivateCopies.push_back(
nullptr);
23433 Inits.push_back(
nullptr);
23440 Type =
Type.getNonReferenceType().getUnqualifiedType();
23442 auto *VD = dyn_cast<VarDecl>(
D);
23446 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23447 << 0 << RefExpr->getSourceRange();
23455 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
23456 if (VDPrivate->isInvalidDecl())
23461 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23477 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23478 PrivateCopies.push_back(VDPrivateRefExpr);
23479 Inits.push_back(VDInitRefExpr);
23484 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23488 MVLI.VarBaseDeclarations.push_back(
D);
23489 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23490 MVLI.VarComponents.back().emplace_back(SimpleRefExpr,
D,
23494 if (MVLI.ProcessedVarList.empty())
23498 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23499 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23505 MappableVarListInfo MVLI(VarList);
23507 for (
Expr *RefExpr : VarList) {
23508 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
23511 Expr *SimpleRefExpr = RefExpr;
23516 MVLI.ProcessedVarList.push_back(RefExpr);
23521 auto *VD = dyn_cast<VarDecl>(
D);
23528 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23533 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23537 MVLI.VarBaseDeclarations.push_back(
D);
23538 MVLI.VarComponents.emplace_back();
23539 Expr *Component = SimpleRefExpr;
23540 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23541 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23544 MVLI.VarComponents.back().emplace_back(Component,
D,
23548 if (MVLI.ProcessedVarList.empty())
23552 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23553 MVLI.VarComponents);
23559 MappableVarListInfo MVLI(VarList);
23560 for (
Expr *RefExpr : VarList) {
23561 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
23564 Expr *SimpleRefExpr = RefExpr;
23568 MVLI.ProcessedVarList.push_back(RefExpr);
23578 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23579 << 0 << RefExpr->getSourceRange();
23585 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
23588 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23591 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
23597 const Expr *ConflictExpr;
23598 if (
DSAStack->checkMappableExprComponentListsForDecl(
23603 ConflictExpr = R.front().getAssociatedExpression();
23606 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23615 SimpleRefExpr,
D,
false);
23616 DSAStack->addMappableExpressionComponents(
23617 D, MC, OMPC_is_device_ptr);
23620 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23625 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23626 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23627 "Unexpected device pointer expression!");
23628 MVLI.VarBaseDeclarations.push_back(
23629 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
23630 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23631 MVLI.VarComponents.back().push_back(MC);
23634 if (MVLI.ProcessedVarList.empty())
23638 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23639 MVLI.VarComponents);
23645 MappableVarListInfo MVLI(VarList);
23646 for (
Expr *RefExpr : VarList) {
23647 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
23650 Expr *SimpleRefExpr = RefExpr;
23655 MVLI.ProcessedVarList.push_back(RefExpr);
23663 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
23666 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23669 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
23675 const Expr *ConflictExpr;
23676 if (
DSAStack->checkMappableExprComponentListsForDecl(
23681 ConflictExpr = R.front().getAssociatedExpression();
23684 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23692 Expr *Component = SimpleRefExpr;
23693 auto *VD = dyn_cast<VarDecl>(
D);
23694 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23695 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23699 Component,
D,
false);
23700 DSAStack->addMappableExpressionComponents(
23701 D, MC, OMPC_has_device_addr);
23707 assert(Ref &&
"has_device_addr capture failed");
23708 MVLI.ProcessedVarList.push_back(Ref);
23710 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23715 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23716 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23717 "Unexpected device pointer expression!");
23718 MVLI.VarBaseDeclarations.push_back(
23719 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
23720 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23721 MVLI.VarComponents.back().push_back(MC);
23724 if (MVLI.ProcessedVarList.empty())
23728 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23729 MVLI.VarComponents);
23743 bool AllocDependent =
23744 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23745 Allocator->isInstantiationDependent() ||
23746 Allocator->containsUnexpandedParameterPack());
23747 if (!AllocDependent) {
23757 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
23762 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
23779 if (!AlignmentDependent) {
23782 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
23787 for (
Expr *RefExpr : VarList) {
23788 assert(RefExpr &&
"NULL expr in OpenMP allocate clause.");
23791 Expr *SimpleRefExpr = RefExpr;
23795 Vars.push_back(RefExpr);
23801 auto *VD = dyn_cast<VarDecl>(
D);
23806 ? RefExpr->IgnoreParens()
23814 DSAStack->addInnerAllocatorExpr(Allocator);
23817 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
23818 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
23819 SecondAllocateModifierLoc, EndLoc, Vars);
23827 for (
Expr *RefExpr : VarList) {
23828 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23831 Expr *SimpleRefExpr = RefExpr;
23835 Vars.push_back(RefExpr);
23842 if (
const Expr *PrevRef =
23843 DSAStack->addUniqueNontemporal(
D, SimpleRefExpr)) {
23844 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23846 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23851 Vars.push_back(RefExpr);
23879 for (
Expr *RefExpr : VarList) {
23880 assert(RefExpr &&
"NULL expr in OpenMP inclusive clause.");
23883 Expr *SimpleRefExpr = RefExpr;
23888 Vars.push_back(RefExpr);
23893 const DSAStackTy::DSAVarData DVar =
23899 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23900 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23901 << RefExpr->getSourceRange();
23903 if (
DSAStack->getParentDirective() != OMPD_unknown)
23904 DSAStack->markDeclAsUsedInScanDirective(
D);
23905 Vars.push_back(RefExpr);
23920 for (
Expr *RefExpr : VarList) {
23921 assert(RefExpr &&
"NULL expr in OpenMP exclusive clause.");
23924 Expr *SimpleRefExpr = RefExpr;
23929 Vars.push_back(RefExpr);
23935 DSAStackTy::DSAVarData DVar;
23936 if (ParentDirective != OMPD_unknown)
23942 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23943 DVar.Modifier != OMPC_REDUCTION_inscan) {
23944 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23945 << RefExpr->getSourceRange();
23947 DSAStack->markDeclAsUsedInScanDirective(
D);
23949 Vars.push_back(RefExpr);
23961 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23962 if (!OMPAlloctraitT.
isNull())
23967 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
23970 Stack->setOMPAlloctraitT(PT.
get());
23990 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23991 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
23992 StringRef Allocator =
23993 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24001 Expr *AllocatorExpr =
nullptr;
24003 if (
D.Allocator->isTypeDependent()) {
24004 AllocatorExpr =
D.Allocator;
24008 AllocatorExpr =
D.Allocator->IgnoreParenImpCasts();
24009 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24010 bool IsPredefinedAllocator =
false;
24012 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24014 IsPredefinedAllocator =
24016 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24020 bool IsTypeCompatible = IsPredefinedAllocator;
24021 IsTypeCompatible = IsTypeCompatible ||
24023 OMPAllocatorHandleT);
24025 IsTypeCompatible ||
24027 bool IsNonConstantLValue =
24029 if (!DRE || !IsTypeCompatible ||
24030 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24031 Diag(
D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24032 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
24039 if (IsPredefinedAllocator &&
D.AllocatorTraits) {
24040 Diag(
D.AllocatorTraits->getExprLoc(),
24041 diag::err_omp_predefined_allocator_with_traits)
24043 Diag(
D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24044 << cast<NamedDecl>(DRE->
getDecl())->getName()
24051 if (!IsPredefinedAllocator && !
D.AllocatorTraits) {
24052 Diag(
D.Allocator->getExprLoc(),
24053 diag::err_omp_nonpredefined_allocator_without_traits);
24057 if (!
D.AllocatorTraits)
24061 IsPredefinedAllocator
24062 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24063 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24065 Expr *AllocatorTraitsExpr =
nullptr;
24066 if (
D.AllocatorTraits) {
24067 if (
D.AllocatorTraits->isTypeDependent()) {
24068 AllocatorTraitsExpr =
D.AllocatorTraits;
24074 AllocatorTraitsExpr =
D.AllocatorTraits->IgnoreParenImpCasts();
24079 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24080 TraitTy = ConstArrayTy->getElementType();
24086 Diag(
D.AllocatorTraits->getExprLoc(),
24087 diag::err_omp_expected_array_alloctraits)
24088 << AllocatorTraitsExpr->
getType();
24093 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24096 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24113 for (
Expr *RefExpr : Locators) {
24114 assert(RefExpr &&
"NULL expr in OpenMP affinity clause.");
24115 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24117 Vars.push_back(RefExpr);
24125 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24126 << 1 << 0 << RefExpr->getSourceRange();
24137 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24138 << 1 << 0 << RefExpr->getSourceRange();
24145 ColonLoc, EndLoc, Modifier, Vars);
24154 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24162 LParenLoc, EndLoc);
24169 Expr *ValExpr = Size;
24170 Stmt *HelperValStmt =
nullptr;
24181 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
24182 if (CaptureRegion != OMPD_unknown &&
24185 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24186 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24191 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24199 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
24200 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24201 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24202 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
24203 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24210 llvm::APSInt TotalDepCount(32);
24213 DepType == OMPC_DOACROSS_source ||
24214 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24215 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24217 Vars = VarOffset.Vars;
24218 OpsOffs = VarOffset.OpsOffs;
24219 TotalDepCount = VarOffset.TotalDepCount;
24221 EndLoc, DepType, DepLoc, ColonLoc, Vars,
24222 TotalDepCount.getZExtValue());
24223 if (
DSAStack->isParentOrderedRegion())
24224 DSAStack->addDoacrossDependClause(
C, OpsOffs);
24253 case OMPC_contains:
24256 llvm_unreachable(
"Unexpected OpenMP clause");
24264 case OMPC_no_openmp:
24266 case OMPC_no_openmp_routines:
24268 case OMPC_no_parallelism:
24270 case OMPC_no_openmp_constructs:
24273 llvm_unreachable(
"Unexpected OpenMP clause");
24282 if (
Base->hasPlaceholderType() &&
24283 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24296 LowerBound =
Result.get();
24298 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24318 if (
Base->isTypeDependent() ||
24321 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24325 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24337 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
24338 <<
Base->getSourceRange());
24344 if (Res.isInvalid())
24346 diag::err_omp_typecheck_section_not_integer)
24348 LowerBound = Res.get();
24358 if (Res.isInvalid())
24360 diag::err_omp_typecheck_section_not_integer)
24361 << 1 << Length->getSourceRange());
24362 Length = Res.get();
24364 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24365 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24366 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
24367 << 1 << Length->getSourceRange();
24374 diag::err_omp_typecheck_section_not_integer)
24376 Stride = Res.
get();
24389 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
24390 << ResultTy <<
Base->getSourceRange();
24395 diag::err_omp_section_incomplete_type,
Base))
24403 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
24404 if (LowerBoundValue.isNegative()) {
24406 diag::err_omp_section_not_subset_of_array)
24415 if (Length->EvaluateAsInt(
Result, Context)) {
24418 llvm::APSInt LengthValue =
Result.Val.getInt();
24419 if (LengthValue.isNegative()) {
24420 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
24421 <<
toString(LengthValue, 10,
true)
24422 << Length->getSourceRange();
24432 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
24442 llvm::APSInt StrideValue =
Result.Val.getInt();
24443 if (!StrideValue.isStrictlyPositive()) {
24444 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
24445 <<
toString(StrideValue, 10,
true)
24452 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24460 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24467 if (
Base->hasPlaceholderType()) {
24481 LParenLoc, RParenLoc, Dims, Brackets);
24483 (!
Base->isTypeDependent() &&
24486 diag::err_omp_non_pointer_type_array_shaping_base)
24487 <<
Base->getSourceRange());
24490 bool ErrorFound =
false;
24492 if (
Dim->hasPlaceholderType()) {
24494 if (
Result.isInvalid()) {
24499 if (
Result.isInvalid()) {
24505 if (!
Dim->isTypeDependent()) {
24508 if (
Result.isInvalid()) {
24510 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
24511 <<
Dim->getSourceRange();
24516 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
24521 if (!
Value.isStrictlyPositive()) {
24522 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
24524 <<
Dim->getSourceRange();
24530 NewDims.push_back(
Dim);
24535 LParenLoc, RParenLoc, NewDims, Brackets);
24545 bool IsCorrect =
true;
24550 if (!
D.Type.getAsOpaquePtr()) {
24554 DeclTy = Context.
IntTy;
24555 StartLoc =
D.DeclIdentLoc;
24561 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24562 DeclTy->containsUnexpandedParameterPack() ||
24563 DeclTy->isInstantiationDependentType();
24564 if (!IsDeclTyDependent) {
24565 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24568 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24573 if (DeclTy.isConstant(Context)) {
24576 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24584 assert(
D.DeclIdent &&
"Identifier expected.");
24589 D.DeclIdent, DeclTy, TInfo,
SC_None);
24595 RedeclarationKind::ForVisibleRedeclaration);
24617 if (!IsDeclTyDependent &&
Begin && !
Begin->isTypeDependent()) {
24622 Expr *End =
D.Range.End;
24623 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24626 End = EndRes.
get();
24628 Expr *Step =
D.Range.Step;
24631 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
24636 std::optional<llvm::APSInt>
Result =
24642 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24648 if (!
Begin || !End || !IsCorrect) {
24664 if (
Decl *ID =
D.IteratorDecl)
24665 ID->setInvalidDecl();
24677 D.Range.End,
D.Range.Begin);
24683 if (
D.Range.Step) {
24694 D.AssignmentLoc, BO_Sub, Res.
get(),
24711 D.AssignmentLoc, BO_Sub,
D.Range.Begin,
D.Range.End);
24725 D.AssignmentLoc, BO_Sub, Res1.
get(),
24740 D.AssignmentLoc, BO_GT,
D.Range.Step,
24765 CounterVD->setImplicit();
24772 if (
D.Range.Step) {
24774 D.AssignmentLoc, BO_Mul,
24784 D.Range.Begin, UpdateRes.
get());
24791 cast<VarDecl>(
D.IteratorDecl)->getType(),
24794 VDRes.
get(), UpdateRes.
get());
24806 D.AssignmentLoc, UO_PreInc, RefRes.
get());
24807 if (!CounterUpdateRes.
isUsable()) {
24813 if (!CounterUpdateRes.
isUsable()) {
24824 Helpers.assign(ID.size(), {});
24829 if (
Decl *ID =
D.IteratorDecl)
24830 ID->setInvalidDecl();
24835 LLoc, RLoc, ID, Helpers);
24840 StringRef AssumptionStr) {
24841 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
24844 unsigned BestEditDistance = 3;
24845 StringRef Suggestion;
24846 for (
const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
24847 unsigned EditDistance =
24848 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24849 if (EditDistance < BestEditDistance) {
24850 Suggestion = KnownAssumptionIt.getKey();
24851 BestEditDistance = EditDistance;
24855 if (!Suggestion.empty())
24856 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24857 << AssumptionStr << Suggestion;
24859 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown)
24876 :
SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
enum clang::sema::@1840::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 Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static 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 bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static 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 std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be 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)
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override
bool VisitVarDecl(VarDecl *D) override
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F) override
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
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 mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
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.
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 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.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return a non-unique reference to the type for a variable array of the specified element type.
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.
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
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.
QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
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]).
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
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.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context semantically encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getEndLoc() const
const DeclGroupRef getDeclGroup() const
const Decl * getSingleDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
bool isReferenced() const
Whether any declaration of this entity was referenced.
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
bool isInvalidDecl() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
void setAccess(AccessSpecifier AS)
SourceLocation getLocation() const
void setImplicit(bool I=true)
void setReferenced(bool R=true)
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
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.
Recursive AST visitor that supports extension via dynamic dispatch.
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,...
bool isIntegerConstantExpr(const ASTContext &Ctx) const
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
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.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
bool 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.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
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, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the '#pragma omp ...' directive.
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)
This represents clause 'lastprivate' in the '#pragma omp ...' directives.
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 the 'message' clause in the '#pragma omp error' and the '#pragma omp parallel' direct...
Expr * getMessageString() const
Returns message string of the clause.
std::optional< std::string > tryEvaluateString(ASTContext &Ctx) const
Try to evaluate the message string at compile time.
This represents the 'no_openmp' clause in the '#pragma omp assume' directive.
This represents the 'no_openmp_constructs' clause in the.
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.
This represents clause 'nontemporal' in the '#pragma omp ...' directives.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the '#pragma omp ...' directive.
This represents '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 class represents the 'permutation' clause in the '#pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents '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, ArrayRef< bool > IsPrivateVarReduction, OpenMPOriginalSharingModifier OriginalSharingModifier)
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, unsigned NumLoops, 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 'self_maps' clause in the '#pragma omp requires' directive.
This represents 'seq_cst' clause in the '#pragma omp atomic|flush' directives.
This represents the 'severity' clause in the '#pragma omp error' and the '#pragma omp parallel' direc...
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 OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp stripe'.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static 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.
This represents clause 'uses_allocators' in the '#pragma omp target'-based directives.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
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 ASTContext &Ctx) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
const Type * getTypePtrOrNull() const
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
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...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
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...
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'to' clause.
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * 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)
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< Expr * > AdjustArgsNeedDeviceAddr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' 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)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'task_reduction' clause.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
StmtResult ActOnOpenMPStripeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interchange' after parsing of its clauses and the associated state...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
void setOpenMPDeviceNumID(StringRef ID)
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
int getOpenMPDeviceNum() const
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
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 * ActOnOpenMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
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 ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'reduction' clause.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp tile' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
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 for '#pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Abstract base class used for diagnosing integer constant expression violations.
Sema - This implements semantic analysis and AST building for C.
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 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)
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt={})
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
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)
FPOptionsOverride CurFPFeatureOverrides()
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
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.
bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, CXXRecordDecl *Base, CXXBasePaths &Paths)
Determine whether the type Derived is a C++ class that is derived from the type Base.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
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
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=AllowFoldKind::No)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
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.
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
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)
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.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
bool isArithmeticType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isScalarType() const
bool isVariableArrayType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isFunctionProtoType() const
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
bool isFunctionType() const
bool isStructureOrClassType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool isFunctionNoProtoType() const
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.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
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.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
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 isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
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.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
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
@ None
No keyword precedes the qualified type name.
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.
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.
int const char * function
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.
int OriginalSharingModifier
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.