40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.h"
44#include "llvm/ADT/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"
53using namespace llvm::omp;
66enum DefaultDataSharingAttributes {
71 DSA_firstprivate = 1 << 3,
81 unsigned Modifier = 0;
82 const Expr *RefExpr =
nullptr;
85 bool AppliedToPointee =
false;
86 DSAVarData() =
default;
90 bool AppliedToPointee)
91 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
92 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
93 AppliedToPointee(AppliedToPointee) {}
95 using OperatorOffsetTy =
97 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
99 enum class UsesAllocatorsDeclKind {
103 UserDefinedAllocator,
111 unsigned Modifier = 0;
114 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
118 bool AppliedToPointee =
false;
120 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
121 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
122 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
123 using LoopControlVariablesMapTy =
124 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
127 struct MappedExprComponentTy {
131 using MappedExprComponentsTy =
132 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
133 using CriticalsWithHintsTy =
134 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
135 struct ReductionData {
136 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
138 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
139 ReductionData() =
default;
146 ReductionOp = RefExpr;
149 using DeclReductionMapTy =
150 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
151 struct DefaultmapInfo {
155 DefaultmapInfo() =
default;
157 : ImplicitBehavior(M), SLoc(
Loc) {}
160 struct SharingMapTy {
161 DeclSAMapTy SharingMap;
162 DeclReductionMapTy ReductionMap;
163 UsedRefMapTy AlignedMap;
164 UsedRefMapTy NontemporalMap;
165 MappedExprComponentsTy MappedExprComponents;
166 LoopControlVariablesMapTy LCVMap;
167 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
172 Scope *CurScope =
nullptr;
178 DoacrossClauseMapTy DoacrossDepends;
182 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
183 bool RegionHasOrderConcurrent =
false;
184 unsigned AssociatedLoops = 1;
185 bool HasMutipleLoops =
false;
186 const Decl *PossiblyLoopCounter =
nullptr;
187 bool NowaitRegion =
false;
188 bool UntiedRegion =
false;
189 bool CancelRegion =
false;
190 bool LoopStart =
false;
191 bool BodyComplete =
false;
196 Expr *TaskgroupReductionRef =
nullptr;
205 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
209 struct ImplicitDefaultFDInfoTy {
213 size_t StackLevel = 0;
216 ImplicitDefaultFDInfoTy(
const FieldDecl *FD,
size_t StackLevel,
218 : FD(FD), StackLevel(StackLevel), VD(VD) {}
222 ImplicitDefaultFirstprivateFDs;
223 Expr *DeclareMapperVar =
nullptr;
227 :
Directive(DKind), DirectiveName(Name), CurScope(CurScope),
229 SharingMapTy() =
default;
235 DeclSAMapTy Threadprivates;
242 bool ForceCapturing =
false;
245 bool ForceCaptureByReferenceInTargetExecutable =
false;
246 CriticalsWithHintsTy Criticals;
247 unsigned IgnoredStackElements = 0;
251 using const_iterator = StackTy::const_reverse_iterator;
252 const_iterator begin()
const {
253 return Stack.empty() ? const_iterator()
254 : Stack.back().first.rbegin() + IgnoredStackElements;
256 const_iterator end()
const {
257 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
259 using iterator = StackTy::reverse_iterator;
261 return Stack.empty() ? iterator()
262 : Stack.back().first.rbegin() + IgnoredStackElements;
265 return Stack.empty() ? iterator() : Stack.back().first.rend();
270 bool isStackEmpty()
const {
271 return Stack.empty() ||
272 Stack.back().second != CurrentNonCapturingFunctionScope ||
273 Stack.back().first.size() <= IgnoredStackElements;
275 size_t getStackSize()
const {
276 return isStackEmpty() ? 0
277 : Stack.back().first.size() - IgnoredStackElements;
280 SharingMapTy *getTopOfStackOrNull() {
281 size_t Size = getStackSize();
284 return &Stack.back().first[
Size - 1];
286 const SharingMapTy *getTopOfStackOrNull()
const {
287 return const_cast<DSAStackTy &
>(*this).getTopOfStackOrNull();
289 SharingMapTy &getTopOfStack() {
290 assert(!isStackEmpty() &&
"no current directive");
291 return *getTopOfStackOrNull();
293 const SharingMapTy &getTopOfStack()
const {
294 return const_cast<DSAStackTy &
>(*this).getTopOfStack();
297 SharingMapTy *getSecondOnStackOrNull() {
298 size_t Size = getStackSize();
301 return &Stack.back().first[
Size - 2];
303 const SharingMapTy *getSecondOnStackOrNull()
const {
304 return const_cast<DSAStackTy &
>(*this).getSecondOnStackOrNull();
313 SharingMapTy &getStackElemAtLevel(
unsigned Level) {
314 assert(Level < getStackSize() &&
"no such stack element");
315 return Stack.back().first[
Level];
317 const SharingMapTy &getStackElemAtLevel(
unsigned Level)
const {
318 return const_cast<DSAStackTy &
>(*this).getStackElemAtLevel(Level);
324 bool isOpenMPLocal(
VarDecl *
D, const_iterator
Iter)
const;
337 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
346 explicit DSAStackTy(
Sema &S) : SemaRef(S) {}
349 void setOMPAllocatorHandleT(
QualType Ty) { OMPAllocatorHandleT = Ty; }
351 QualType getOMPAllocatorHandleT()
const {
return OMPAllocatorHandleT; }
353 void setOMPAlloctraitT(
QualType Ty) { OMPAlloctraitT = Ty; }
355 QualType getOMPAlloctraitT()
const {
return OMPAlloctraitT; }
357 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
359 OMPPredefinedAllocators[AllocatorKind] = Allocator;
362 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind)
const {
363 return OMPPredefinedAllocators[AllocatorKind];
366 void setOMPDependT(
QualType Ty) { OMPDependT = Ty; }
368 QualType getOMPDependT()
const {
return OMPDependT; }
371 void setOMPEventHandleT(
QualType Ty) { OMPEventHandleT = Ty; }
373 QualType getOMPEventHandleT()
const {
return OMPEventHandleT; }
375 bool isClauseParsingMode()
const {
return ClauseKindMode != OMPC_unknown; }
377 assert(isClauseParsingMode() &&
"Must be in clause parsing mode.");
378 return ClauseKindMode;
382 bool isBodyComplete()
const {
383 const SharingMapTy *Top = getTopOfStackOrNull();
384 return Top && Top->BodyComplete;
386 void setBodyComplete() { getTopOfStack().BodyComplete =
true; }
388 bool isForceVarCapturing()
const {
return ForceCapturing; }
389 void setForceVarCapturing(
bool V) { ForceCapturing =
V; }
391 void setForceCaptureByReferenceInTargetExecutable(
bool V) {
392 ForceCaptureByReferenceInTargetExecutable =
V;
394 bool isForceCaptureByReferenceInTargetExecutable()
const {
395 return ForceCaptureByReferenceInTargetExecutable;
400 assert(!IgnoredStackElements &&
401 "cannot change stack while ignoring elements");
403 Stack.back().second != CurrentNonCapturingFunctionScope)
404 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
405 Stack.back().first.emplace_back(DKind, DirName, CurScope,
Loc);
406 Stack.back().first.back().DefaultAttrLoc =
Loc;
410 assert(!IgnoredStackElements &&
411 "cannot change stack while ignoring elements");
412 assert(!Stack.back().first.empty() &&
413 "Data-sharing attributes stack is empty!");
414 Stack.back().first.pop_back();
419 class ParentDirectiveScope {
424 ParentDirectiveScope(DSAStackTy &Self,
bool Activate)
425 : Self(Self), Active(
false) {
429 ~ParentDirectiveScope() { disable(); }
432 --Self.IgnoredStackElements;
438 ++Self.IgnoredStackElements;
447 "Expected loop-based directive.");
448 getTopOfStack().LoopStart =
true;
453 "Expected loop-based directive.");
454 getTopOfStack().LoopStart =
false;
457 bool isLoopStarted()
const {
459 "Expected loop-based directive.");
460 return !getTopOfStack().LoopStart;
463 void resetPossibleLoopCounter(
const Decl *
D =
nullptr) {
467 const Decl *getPossiblyLoopCounter()
const {
468 return getTopOfStack().PossiblyLoopCounter;
471 void pushFunction() {
472 assert(!IgnoredStackElements &&
473 "cannot change stack while ignoring elements");
475 assert(!isa<CapturingScopeInfo>(CurFnScope));
476 CurrentNonCapturingFunctionScope = CurFnScope;
480 assert(!IgnoredStackElements &&
481 "cannot change stack while ignoring elements");
482 if (!Stack.empty() && Stack.back().second == OldFSI) {
483 assert(Stack.back().first.empty());
486 CurrentNonCapturingFunctionScope =
nullptr;
488 if (!isa<CapturingScopeInfo>(FSI)) {
489 CurrentNonCapturingFunctionScope = FSI;
496 Criticals.try_emplace(
D->getDirectiveName().getAsString(),
D, Hint);
498 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
500 auto I = Criticals.find(Name.getAsString());
501 if (I != Criticals.end())
503 return std::make_pair(
nullptr, llvm::APSInt());
520 const LCDeclInfo isLoopControlVariable(
const ValueDecl *
D)
const;
525 const LCDeclInfo isParentLoopControlVariable(
const ValueDecl *
D)
const;
530 const LCDeclInfo isLoopControlVariable(
const ValueDecl *
D,
531 unsigned Level)
const;
534 const ValueDecl *getParentLoopControlVariable(
unsigned I)
const;
537 void markDeclAsUsedInScanDirective(
ValueDecl *
D) {
538 if (SharingMapTy *Stack = getSecondOnStackOrNull())
539 Stack->UsedInScanDirective.insert(
D);
543 bool isUsedInScanDirective(
ValueDecl *
D)
const {
544 if (
const SharingMapTy *Stack = getTopOfStackOrNull())
545 return Stack->UsedInScanDirective.contains(
D);
551 DeclRefExpr *PrivateCopy =
nullptr,
unsigned Modifier = 0,
552 bool AppliedToPointee =
false);
561 const Expr *ReductionRef);
567 Expr *&TaskgroupDescriptor)
const;
572 const Expr *&ReductionRef,
573 Expr *&TaskgroupDescriptor)
const;
576 Expr *getTaskgroupReductionRef()
const {
577 assert((getTopOfStack().
Directive == OMPD_taskgroup ||
581 "taskgroup reference expression requested for non taskgroup or "
582 "parallel/worksharing directive.");
583 return getTopOfStack().TaskgroupReductionRef;
587 bool isTaskgroupReductionRef(
const ValueDecl *VD,
unsigned Level)
const {
588 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
589 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
595 const DSAVarData getTopDSA(
ValueDecl *
D,
bool FromParent);
597 const DSAVarData getImplicitDSA(
ValueDecl *
D,
bool FromParent)
const;
599 const DSAVarData getImplicitDSA(
ValueDecl *
D,
unsigned Level)
const;
606 DefaultDataSharingAttributes)>
609 bool FromParent)
const;
617 bool FromParent)
const;
624 unsigned Level,
bool NotLastprivate =
false)
const;
628 bool hasExplicitDirective(
630 unsigned Level)
const;
634 const llvm::function_ref<
bool(
637 bool FromParent)
const;
641 const SharingMapTy *Top = getTopOfStackOrNull();
642 return Top ? Top->Directive : OMPD_unknown;
646 assert(!isStackEmpty() &&
"No directive at specified level.");
647 return getStackElemAtLevel(Level).Directive;
651 unsigned OpenMPCaptureLevel)
const {
654 return CaptureRegions[OpenMPCaptureLevel];
658 const SharingMapTy *
Parent = getSecondOnStackOrNull();
663 void addRequiresDecl(
OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
666 template <
typename ClauseType>
bool hasRequiresDeclWithClause()
const {
668 return llvm::any_of(
D->clauselists(), [](
const OMPClause *
C) {
669 return isa<ClauseType>(C);
677 bool IsDuplicate =
false;
680 for (
const OMPClause *CPrev :
D->clauselists()) {
681 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
682 SemaRef.
Diag(CNew->getBeginLoc(),
683 diag::err_omp_requires_clause_redeclaration)
684 << getOpenMPClauseName(CNew->getClauseKind());
685 SemaRef.
Diag(CPrev->getBeginLoc(),
686 diag::note_omp_requires_previous_clause)
687 << getOpenMPClauseName(CPrev->getClauseKind());
698 TargetLocations.push_back(LocStart);
704 AtomicLocation =
Loc;
709 SourceLocation getAtomicDirectiveLoc()
const {
return AtomicLocation; }
713 return TargetLocations;
718 getTopOfStack().DefaultAttr = DSA_none;
719 getTopOfStack().DefaultAttrLoc =
Loc;
723 getTopOfStack().DefaultAttr = DSA_shared;
724 getTopOfStack().DefaultAttrLoc =
Loc;
728 getTopOfStack().DefaultAttr = DSA_private;
729 getTopOfStack().DefaultAttrLoc =
Loc;
733 getTopOfStack().DefaultAttr = DSA_firstprivate;
734 getTopOfStack().DefaultAttrLoc =
Loc;
739 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[
Kind];
740 DMI.ImplicitBehavior = M;
746 return getTopOfStack()
747 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
750 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
753 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
755 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
760 return ConstructTraits;
765 ConstructTraits.append(Traits.begin(), Traits.end());
767 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
768 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
769 assert(Top == Trait &&
"Something left a trait on the stack!");
775 DefaultDataSharingAttributes getDefaultDSA(
unsigned Level)
const {
776 return getStackSize() <=
Level ? DSA_unspecified
777 : getStackElemAtLevel(Level).DefaultAttr;
779 DefaultDataSharingAttributes getDefaultDSA()
const {
780 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
783 return isStackEmpty() ?
SourceLocation() : getTopOfStack().DefaultAttrLoc;
787 return isStackEmpty()
789 : getTopOfStack().DefaultmapMap[
Kind].ImplicitBehavior;
792 getDefaultmapModifierAtLevel(
unsigned Level,
794 return getStackElemAtLevel(Level).DefaultmapMap[
Kind].ImplicitBehavior;
796 bool isDefaultmapCapturedByRef(
unsigned Level,
799 getDefaultmapModifierAtLevel(Level, Kind);
800 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
801 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
802 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom);
811 case OMPC_DEFAULTMAP_scalar:
812 case OMPC_DEFAULTMAP_pointer:
814 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
815 (M == OMPC_DEFAULTMAP_MODIFIER_default);
816 case OMPC_DEFAULTMAP_aggregate:
817 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
821 llvm_unreachable(
"Unexpected OpenMPDefaultmapClauseKind enum");
823 bool mustBeFirstprivateAtLevel(
unsigned Level,
826 getDefaultmapModifierAtLevel(Level, Kind);
827 return mustBeFirstprivateBase(M, Kind);
831 return mustBeFirstprivateBase(M, Kind);
836 const DSAVarData DVar = getTopDSA(
D,
false);
841 void setOrderedRegion(
bool IsOrdered,
const Expr *Param,
844 getTopOfStack().OrderedRegion.emplace(Param, Clause);
846 getTopOfStack().OrderedRegion.reset();
850 bool isOrderedRegion()
const {
851 if (
const SharingMapTy *Top = getTopOfStackOrNull())
852 return Top->OrderedRegion.has_value();
856 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam()
const {
857 if (
const SharingMapTy *Top = getTopOfStackOrNull())
858 if (Top->OrderedRegion)
859 return *Top->OrderedRegion;
860 return std::make_pair(
nullptr,
nullptr);
864 bool isParentOrderedRegion()
const {
865 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
866 return Parent->OrderedRegion.has_value();
870 std::pair<const Expr *, OMPOrderedClause *>
871 getParentOrderedRegionParam()
const {
872 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
873 if (
Parent->OrderedRegion)
874 return *
Parent->OrderedRegion;
875 return std::make_pair(
nullptr,
nullptr);
878 void setRegionHasOrderConcurrent(
bool HasOrderConcurrent) {
879 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
883 bool isParentOrderConcurrent()
const {
884 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
885 return Parent->RegionHasOrderConcurrent;
889 void setNowaitRegion(
bool IsNowait =
true) {
890 getTopOfStack().NowaitRegion = IsNowait;
894 bool isParentNowaitRegion()
const {
895 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
896 return Parent->NowaitRegion;
900 void setUntiedRegion(
bool IsUntied =
true) {
901 getTopOfStack().UntiedRegion = IsUntied;
904 bool isUntiedRegion()
const {
905 const SharingMapTy *Top = getTopOfStackOrNull();
906 return Top ? Top->UntiedRegion :
false;
909 void setParentCancelRegion(
bool Cancel =
true) {
910 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
911 Parent->CancelRegion |= Cancel;
914 bool isCancelRegion()
const {
915 const SharingMapTy *Top = getTopOfStackOrNull();
916 return Top ? Top->CancelRegion :
false;
921 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
925 bool doesParentHasScanDirective()
const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevScanLocation.isValid() :
false;
931 const SharingMapTy *Top = getSecondOnStackOrNull();
936 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
940 bool doesParentHasOrderedDirective()
const {
941 const SharingMapTy *Top = getSecondOnStackOrNull();
942 return Top ? Top->PrevOrderedLocation.isValid() :
false;
946 const SharingMapTy *Top = getSecondOnStackOrNull();
951 void setAssociatedLoops(
unsigned Val) {
952 getTopOfStack().AssociatedLoops = Val;
954 getTopOfStack().HasMutipleLoops =
true;
957 unsigned getAssociatedLoops()
const {
958 const SharingMapTy *Top = getTopOfStackOrNull();
959 return Top ? Top->AssociatedLoops : 0;
962 bool hasMutipleLoops()
const {
963 const SharingMapTy *Top = getTopOfStackOrNull();
964 return Top ? Top->HasMutipleLoops :
false;
970 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
971 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
974 bool hasInnerTeamsRegion()
const {
975 return getInnerTeamsRegionLoc().
isValid();
979 const SharingMapTy *Top = getTopOfStackOrNull();
983 Scope *getCurScope()
const {
984 const SharingMapTy *Top = getTopOfStackOrNull();
985 return Top ? Top->CurScope :
nullptr;
987 void setContext(
DeclContext *DC) { getTopOfStack().Context = DC; }
989 const SharingMapTy *Top = getTopOfStackOrNull();
995 bool checkMappableExprComponentListsForDecl(
996 const ValueDecl *VD,
bool CurrentRegionOnly,
997 const llvm::function_ref<
1009 if (CurrentRegionOnly)
1012 std::advance(SI, 1);
1014 for (; SI != SE; ++SI) {
1015 auto MI = SI->MappedExprComponents.find(VD);
1016 if (MI != SI->MappedExprComponents.end())
1018 MI->second.Components)
1019 if (Check(L, MI->second.Kind))
1027 bool checkMappableExprComponentListsForDeclAtLevel(
1029 const llvm::function_ref<
1033 if (getStackSize() <= Level)
1036 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1037 auto MI = StackElem.MappedExprComponents.find(VD);
1038 if (MI != StackElem.MappedExprComponents.end())
1040 MI->second.Components)
1041 if (Check(L, MI->second.Kind))
1048 void addMappableExpressionComponents(
1052 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1054 MEC.Components.resize(MEC.Components.size() + 1);
1055 MEC.Components.back().append(Components.begin(), Components.end());
1056 MEC.Kind = WhereFoundClauseKind;
1059 unsigned getNestingLevel()
const {
1060 assert(!isStackEmpty());
1061 return getStackSize() - 1;
1063 void addDoacrossDependClause(
OMPClause *
C,
const OperatorOffsetTy &OpsOffs) {
1064 SharingMapTy *
Parent = getSecondOnStackOrNull();
1066 Parent->DoacrossDepends.try_emplace(
C, OpsOffs);
1068 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1069 getDoacrossDependClauses()
const {
1070 const SharingMapTy &StackElem = getTopOfStack();
1072 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1073 return llvm::make_range(Ref.begin(), Ref.end());
1075 return llvm::make_range(StackElem.DoacrossDepends.end(),
1076 StackElem.DoacrossDepends.end());
1080 void addMappedClassesQualTypes(
QualType QT) {
1081 SharingMapTy &StackElem = getTopOfStack();
1082 StackElem.MappedClassesQualTypes.insert(QT);
1086 bool isClassPreviouslyMapped(
QualType QT)
const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 return StackElem.MappedClassesQualTypes.contains(QT);
1092 void addToParentTargetRegionLinkGlobals(
DeclRefExpr *
E) {
1093 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1094 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1095 "Expected declare target link global.");
1096 for (
auto &Elem : *
this) {
1098 Elem.DeclareTargetLinkVarDecls.push_back(
E);
1108 "Expected target executable directive.");
1109 return getTopOfStack().DeclareTargetLinkVarDecls;
1113 void addInnerAllocatorExpr(
Expr *
E) {
1114 getTopOfStack().InnerUsedAllocators.push_back(
E);
1118 return getTopOfStack().InnerUsedAllocators;
1122 void addImplicitTaskFirstprivate(
unsigned Level,
Decl *
D) {
1123 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(
D);
1126 bool isImplicitTaskFirstprivate(
Decl *
D)
const {
1127 return getTopOfStack().ImplicitTaskFirstprivates.contains(
D);
1131 void addUsesAllocatorsDecl(
const Decl *
D, UsesAllocatorsDeclKind Kind) {
1132 getTopOfStack().UsesAllocatorsDecls.try_emplace(
D, Kind);
1136 std::optional<UsesAllocatorsDeclKind>
1137 isUsesAllocatorsDecl(
unsigned Level,
const Decl *
D)
const {
1138 const SharingMapTy &StackElem = getTopOfStack();
1139 auto I = StackElem.UsesAllocatorsDecls.find(
D);
1140 if (I == StackElem.UsesAllocatorsDecls.end())
1141 return std::nullopt;
1142 return I->getSecond();
1144 std::optional<UsesAllocatorsDeclKind>
1145 isUsesAllocatorsDecl(
const Decl *
D)
const {
1146 const SharingMapTy &StackElem = getTopOfStack();
1147 auto I = StackElem.UsesAllocatorsDecls.find(
D);
1148 if (I == StackElem.UsesAllocatorsDecls.end())
1149 return std::nullopt;
1150 return I->getSecond();
1153 void addDeclareMapperVarRef(
Expr *Ref) {
1154 SharingMapTy &StackElem = getTopOfStack();
1155 StackElem.DeclareMapperVar = Ref;
1157 const Expr *getDeclareMapperVarRef()
const {
1158 const SharingMapTy *Top = getTopOfStackOrNull();
1159 return Top ? Top->DeclareMapperVar :
nullptr;
1163 void addIteratorVarDecl(
VarDecl *VD) {
1164 SharingMapTy &StackElem = getTopOfStack();
1168 bool isIteratorVarDecl(
const VarDecl *VD)
const {
1169 const SharingMapTy *Top = getTopOfStackOrNull();
1177 const_iterator I = begin();
1178 const_iterator EndI = end();
1179 size_t StackLevel = getStackSize();
1180 for (; I != EndI; ++I) {
1181 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1185 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1188 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1189 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1194 bool isImplicitDefaultFirstprivateFD(
VarDecl *VD)
const {
1195 const_iterator I = begin();
1196 const_iterator EndI = end();
1197 for (; I != EndI; ++I)
1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1202 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1209 iterator I = begin();
1210 const_iterator EndI = end();
1211 size_t StackLevel = getStackSize();
1212 for (; I != EndI; ++I) {
1213 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1214 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1219 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1229 DKind == OMPD_unknown;
1235 if (
const auto *FE = dyn_cast<FullExpr>(
E))
1236 E = FE->getSubExpr();
1238 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
E))
1239 E = MTE->getSubExpr();
1241 while (
const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(
E))
1242 E = Binder->getSubExpr();
1244 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(
E))
1245 E = ICE->getSubExprAsWritten();
1254 if (
const auto *CED = dyn_cast<OMPCapturedExprDecl>(
D))
1255 if (
const auto *ME = dyn_cast<MemberExpr>(
getExprAsWritten(CED->getInit())))
1256 D = ME->getMemberDecl();
1257 const auto *VD = dyn_cast<VarDecl>(
D);
1258 const auto *FD = dyn_cast<FieldDecl>(
D);
1259 if (VD !=
nullptr) {
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 = StackElem.AlignedMap.find(
D);
1414 if (It == StackElem.AlignedMap.end()) {
1415 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1416 StackElem.AlignedMap[
D] = NewDE;
1419 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1424 const Expr *NewDE) {
1425 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1427 SharingMapTy &StackElem = getTopOfStack();
1428 auto It = StackElem.NontemporalMap.find(
D);
1429 if (It == StackElem.NontemporalMap.end()) {
1430 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1431 StackElem.NontemporalMap[
D] = NewDE;
1434 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1439 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1441 SharingMapTy &StackElem = getTopOfStack();
1442 StackElem.LCVMap.try_emplace(
1443 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1446const DSAStackTy::LCDeclInfo
1447DSAStackTy::isLoopControlVariable(
const ValueDecl *
D)
const {
1448 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1450 const SharingMapTy &StackElem = getTopOfStack();
1451 auto It = StackElem.LCVMap.find(
D);
1452 if (It != StackElem.LCVMap.end())
1454 return {0,
nullptr};
1457const DSAStackTy::LCDeclInfo
1458DSAStackTy::isLoopControlVariable(
const ValueDecl *
D,
unsigned Level)
const {
1459 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1461 for (
unsigned I = Level + 1; I > 0; --I) {
1462 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1463 auto It = StackElem.LCVMap.find(
D);
1464 if (It != StackElem.LCVMap.end())
1467 return {0,
nullptr};
1470const DSAStackTy::LCDeclInfo
1471DSAStackTy::isParentLoopControlVariable(
const ValueDecl *
D)
const {
1472 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1473 assert(
Parent &&
"Data-sharing attributes stack is empty");
1475 auto It =
Parent->LCVMap.find(
D);
1476 if (It !=
Parent->LCVMap.end())
1478 return {0,
nullptr};
1481const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1482 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1483 assert(
Parent &&
"Data-sharing attributes stack is empty");
1484 if (
Parent->LCVMap.size() < I)
1486 for (
const auto &Pair :
Parent->LCVMap)
1487 if (Pair.second.first == I)
1494 bool AppliedToPointee) {
1496 if (A == OMPC_threadprivate) {
1497 DSAInfo &
Data = Threadprivates[
D];
1498 Data.Attributes = A;
1499 Data.RefExpr.setPointer(
E);
1500 Data.PrivateCopy =
nullptr;
1501 Data.Modifier = Modifier;
1503 DSAInfo &
Data = getTopOfStack().SharingMap[
D];
1504 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1505 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1506 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1507 (isLoopControlVariable(
D).first && A == OMPC_private));
1508 Data.Modifier = Modifier;
1509 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1510 Data.RefExpr.setInt(
true);
1513 const bool IsLastprivate =
1514 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1515 Data.Attributes = A;
1516 Data.RefExpr.setPointerAndInt(
E, IsLastprivate);
1517 Data.PrivateCopy = PrivateCopy;
1518 Data.AppliedToPointee = AppliedToPointee;
1520 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1521 Data.Modifier = Modifier;
1522 Data.Attributes = A;
1523 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1524 Data.PrivateCopy =
nullptr;
1525 Data.AppliedToPointee = AppliedToPointee;
1532 StringRef Name,
const AttrVec *Attrs =
nullptr,
1547 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1554 bool RefersToCapture =
false) {
1565 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1567 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1568 "Additional reduction info may be specified only for reduction items.");
1569 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1570 assert(ReductionData.ReductionRange.isInvalid() &&
1571 (getTopOfStack().
Directive == OMPD_taskgroup ||
1575 "Additional reduction info may be specified only once for reduction "
1577 ReductionData.set(BOK, SR);
1578 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1579 if (!TaskgroupReductionRef) {
1582 TaskgroupReductionRef =
1588 const Expr *ReductionRef) {
1590 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1592 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1593 "Additional reduction info may be specified only for reduction items.");
1594 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1595 assert(ReductionData.ReductionRange.isInvalid() &&
1596 (getTopOfStack().
Directive == OMPD_taskgroup ||
1600 "Additional reduction info may be specified only once for reduction "
1602 ReductionData.set(ReductionRef, SR);
1603 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1604 if (!TaskgroupReductionRef) {
1607 TaskgroupReductionRef =
1612const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1614 Expr *&TaskgroupDescriptor)
const {
1616 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1617 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1618 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1619 if (
Data.Attributes != OMPC_reduction ||
1620 Data.Modifier != OMPC_REDUCTION_task)
1622 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1623 if (!ReductionData.ReductionOp ||
1624 ReductionData.ReductionOp.is<
const Expr *>())
1625 return DSAVarData();
1626 SR = ReductionData.ReductionRange;
1627 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1628 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1629 "expression for the descriptor is not "
1631 TaskgroupDescriptor = I->TaskgroupReductionRef;
1632 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1633 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1636 return DSAVarData();
1639const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1641 Expr *&TaskgroupDescriptor)
const {
1643 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1644 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1645 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1646 if (
Data.Attributes != OMPC_reduction ||
1647 Data.Modifier != OMPC_REDUCTION_task)
1649 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1650 if (!ReductionData.ReductionOp ||
1651 !ReductionData.ReductionOp.is<
const Expr *>())
1652 return DSAVarData();
1653 SR = ReductionData.ReductionRange;
1654 ReductionRef = ReductionData.ReductionOp.get<
const Expr *>();
1655 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1656 "expression for the descriptor is not "
1658 TaskgroupDescriptor = I->TaskgroupReductionRef;
1659 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1660 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1663 return DSAVarData();
1666bool DSAStackTy::isOpenMPLocal(
VarDecl *
D, const_iterator I)
const {
1668 for (const_iterator
E = end(); I !=
E; ++I) {
1669 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1673 Scope *CurScope = getCurScope();
1674 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(
D))
1676 return CurScope != TopScope;
1679 if (I->Context == DC)
1688 bool AcceptIfMutable =
true,
1689 bool *IsClassType =
nullptr) {
1691 Type =
Type.getNonReferenceType().getCanonicalType();
1692 bool IsConstant =
Type.isConstant(Context);
1697 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1699 RD = CTD->getTemplatedDecl();
1702 return IsConstant && !(SemaRef.
getLangOpts().CPlusPlus && RD &&
1709 bool AcceptIfMutable =
true,
1710 bool ListItemNotVar =
false) {
1714 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1715 : IsClassType ? diag::err_omp_const_not_mutable_variable
1716 : diag::err_omp_const_variable;
1717 SemaRef.
Diag(ELoc,
Diag) << getOpenMPClauseName(CKind);
1718 if (!ListItemNotVar &&
D) {
1719 const VarDecl *VD = dyn_cast<VarDecl>(
D);
1723 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1731const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(
ValueDecl *
D,
1736 auto *VD = dyn_cast<VarDecl>(
D);
1737 auto TI = Threadprivates.find(
D);
1738 if (TI != Threadprivates.end()) {
1739 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1740 DVar.CKind = OMPC_threadprivate;
1741 DVar.Modifier = TI->getSecond().Modifier;
1744 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1746 SemaRef, VD,
D->getType().getNonReferenceType(),
1747 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1748 DVar.CKind = OMPC_threadprivate;
1749 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1756 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1762 SemaRef, VD,
D->getType().getNonReferenceType(),
D->
getLocation());
1763 DVar.CKind = OMPC_threadprivate;
1764 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1769 !isLoopControlVariable(
D).first) {
1770 const_iterator IterTarget =
1771 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1774 if (IterTarget != end()) {
1775 const_iterator ParentIterTarget = IterTarget + 1;
1776 for (const_iterator
Iter = begin();
Iter != ParentIterTarget; ++
Iter) {
1777 if (isOpenMPLocal(VD,
Iter)) {
1781 DVar.CKind = OMPC_threadprivate;
1785 if (!isClauseParsingMode() || IterTarget != begin()) {
1786 auto DSAIter = IterTarget->SharingMap.find(
D);
1787 if (DSAIter != IterTarget->SharingMap.end() &&
1789 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1790 DVar.CKind = OMPC_threadprivate;
1793 const_iterator End = end();
1795 D, std::distance(ParentIterTarget, End),
1799 IterTarget->ConstructLoc);
1800 DVar.CKind = OMPC_threadprivate;
1820 const_iterator I = begin();
1821 const_iterator EndI = end();
1822 if (FromParent && I != EndI)
1825 auto It = I->SharingMap.find(
D);
1826 if (It != I->SharingMap.end()) {
1827 const DSAInfo &
Data = It->getSecond();
1828 DVar.RefExpr =
Data.RefExpr.getPointer();
1829 DVar.PrivateCopy =
Data.PrivateCopy;
1830 DVar.CKind =
Data.Attributes;
1831 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1832 DVar.DKind = I->Directive;
1833 DVar.Modifier =
Data.Modifier;
1834 DVar.AppliedToPointee =
Data.AppliedToPointee;
1839 DVar.CKind = OMPC_shared;
1846 if (SemaRef.
LangOpts.OpenMP <= 31) {
1854 DSAVarData DVarTemp = hasInnermostDSA(
1857 return C == OMPC_firstprivate ||
C == OMPC_shared;
1859 MatchesAlways, FromParent);
1860 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1863 DVar.CKind = OMPC_shared;
1870 const_iterator I = begin();
1871 const_iterator EndI = end();
1872 if (FromParent && I != EndI)
1876 auto It = I->SharingMap.find(
D);
1877 if (It != I->SharingMap.end()) {
1878 const DSAInfo &
Data = It->getSecond();
1879 DVar.RefExpr =
Data.RefExpr.getPointer();
1880 DVar.PrivateCopy =
Data.PrivateCopy;
1881 DVar.CKind =
Data.Attributes;
1882 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1883 DVar.DKind = I->Directive;
1884 DVar.Modifier =
Data.Modifier;
1885 DVar.AppliedToPointee =
Data.AppliedToPointee;
1891const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1892 bool FromParent)
const {
1893 if (isStackEmpty()) {
1895 return getDSA(I,
D);
1898 const_iterator StartI = begin();
1899 const_iterator EndI = end();
1900 if (FromParent && StartI != EndI)
1902 return getDSA(StartI,
D);
1905const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1906 unsigned Level)
const {
1907 if (getStackSize() <= Level)
1908 return DSAVarData();
1910 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1911 return getDSA(StartI,
D);
1914const DSAStackTy::DSAVarData
1917 DefaultDataSharingAttributes)>
1920 bool FromParent)
const {
1924 const_iterator I = begin();
1925 const_iterator EndI = end();
1926 if (FromParent && I != EndI)
1928 for (; I != EndI; ++I) {
1929 if (!DPred(I->Directive) &&
1930 !isImplicitOrExplicitTaskingRegion(I->Directive))
1932 const_iterator NewI = I;
1933 DSAVarData DVar = getDSA(NewI,
D);
1934 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1940const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1943 bool FromParent)
const {
1947 const_iterator StartI = begin();
1948 const_iterator EndI = end();
1949 if (FromParent && StartI != EndI)
1951 if (StartI == EndI || !DPred(StartI->Directive))
1953 const_iterator NewI = StartI;
1954 DSAVarData DVar = getDSA(NewI,
D);
1955 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1960bool DSAStackTy::hasExplicitDSA(
1963 unsigned Level,
bool NotLastprivate)
const {
1964 if (getStackSize() <= Level)
1967 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1968 auto I = StackElem.SharingMap.find(
D);
1969 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1970 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1971 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1974 auto LI = StackElem.LCVMap.find(
D);
1975 if (LI != StackElem.LCVMap.end())
1976 return CPred(OMPC_private,
false);
1980bool DSAStackTy::hasExplicitDirective(
1982 unsigned Level)
const {
1983 if (getStackSize() <= Level)
1985 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1986 return DPred(StackElem.Directive);
1989bool DSAStackTy::hasDirective(
1993 bool FromParent)
const {
1995 size_t Skip = FromParent ? 2 : 1;
1996 for (const_iterator I = begin() + std::min(Skip, getStackSize()),
E = end();
1998 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2004void SemaOpenMP::InitDataSharingAttributesStack() {
2005 VarDataSharingAttributesStack =
new DSAStackTy(
SemaRef);
2008#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2010void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2018 "Expected OpenMP device compilation.");
2024enum class FunctionEmissionStatus {
2035 "Expected OpenMP device compilation.");
2037 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2042 Kind = SemaDiagnosticBuilder::K_Immediate;
2053 ? SemaDiagnosticBuilder::K_Deferred
2054 : SemaDiagnosticBuilder::K_Immediate;
2058 Kind = SemaDiagnosticBuilder::K_Nop;
2061 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2073 "Expected OpenMP host compilation.");
2075 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2080 Kind = SemaDiagnosticBuilder::K_Immediate;
2083 Kind = SemaDiagnosticBuilder::K_Deferred;
2088 Kind = SemaDiagnosticBuilder::K_Nop;
2098 if (LO.OpenMP <= 45) {
2100 return OMPC_DEFAULTMAP_scalar;
2101 return OMPC_DEFAULTMAP_aggregate;
2104 return OMPC_DEFAULTMAP_pointer;
2106 return OMPC_DEFAULTMAP_scalar;
2107 return OMPC_DEFAULTMAP_aggregate;
2111 unsigned OpenMPCaptureLevel)
const {
2112 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2115 bool IsByRef =
true;
2121 bool IsVariableUsedInMapClause =
false;
2183 bool IsVariableAssociatedWithSection =
false;
2185 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2187 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2194 if (WhereFoundClauseKind != OMPC_map &&
2195 WhereFoundClauseKind != OMPC_has_device_addr)
2198 auto EI = MapExprComponents.rbegin();
2199 auto EE = MapExprComponents.rend();
2201 assert(EI != EE &&
"Invalid map expression!");
2203 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2204 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() ==
D;
2209 auto Last = std::prev(EE);
2211 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2212 if ((UO && UO->getOpcode() == UO_Deref) ||
2213 isa<ArraySubscriptExpr>(
Last->getAssociatedExpression()) ||
2214 isa<ArraySectionExpr>(
Last->getAssociatedExpression()) ||
2215 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2216 isa<OMPArrayShapingExpr>(
Last->getAssociatedExpression())) {
2217 IsVariableAssociatedWithSection =
true;
2226 if (IsVariableUsedInMapClause) {
2229 IsByRef = !(Ty->
isPointerType() && IsVariableAssociatedWithSection);
2234 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2237 DSAStack->isDefaultmapCapturedByRef(
2242 return K == OMPC_reduction && !AppliedToPointee;
2250 ((IsVariableUsedInMapClause &&
2251 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2256 return K == OMPC_firstprivate ||
2257 (K == OMPC_reduction && AppliedToPointee);
2260 DSAStack->isUsesAllocatorsDecl(Level,
D))) &&
2263 !(isa<OMPCapturedExprDecl>(
D) && !
D->
hasAttr<OMPCaptureNoInitAttr>() &&
2264 !cast<OMPCapturedExprDecl>(
D)->getInit()->isGLValue()) &&
2267 !((
DSAStack->getDefaultDSA() == DSA_firstprivate ||
2268 DSAStack->getDefaultDSA() == DSA_private) &&
2272 !
DSAStack->isLoopControlVariable(
D, Level).first);
2289unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2291 return DSAStack->getNestingLevel();
2301 !
DSAStack->isClauseParsingMode()) ||
2312 if (!dyn_cast<FieldDecl>(
D))
2314 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2317 DefaultDataSharingAttributes DefaultAttr) {
2319 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2323 if (DVarPrivate.CKind != OMPC_unknown)
2329 Expr *CaptureExpr,
bool WithInit,
2335 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2338 auto *VD = dyn_cast<VarDecl>(
D);
2347 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2357 DSAStackTy::DSAVarData DVarTop =
2359 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2364 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2371 if (!isa<CapturingScopeInfo>(FSI))
2373 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2379 assert(CSI &&
"Failed to find CapturedRegionScopeInfo");
2390 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2396 if (CheckScopeInfo) {
2397 bool OpenMPFound =
false;
2398 for (
unsigned I = StopAt + 1; I > 0; --I) {
2400 if (!isa<CapturingScopeInfo>(FSI))
2402 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2412 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2413 (!
DSAStack->isClauseParsingMode() ||
2414 DSAStack->getParentDirective() != OMPD_unknown)) {
2415 auto &&Info =
DSAStack->isLoopControlVariable(
D);
2418 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2419 (VD &&
DSAStack->isForceVarCapturing()))
2420 return VD ? VD : Info.second;
2421 DSAStackTy::DSAVarData DVarTop =
2423 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2425 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2431 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2439 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2440 ((
DSAStack->getDefaultDSA() != DSA_none &&
2441 DSAStack->getDefaultDSA() != DSA_private &&
2442 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2443 DVarTop.CKind == OMPC_shared))
2445 auto *FD = dyn_cast<FieldDecl>(
D);
2446 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2447 !DVarPrivate.PrivateCopy) {
2448 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2451 DefaultDataSharingAttributes DefaultAttr) {
2453 (DefaultAttr == DSA_firstprivate ||
2454 DefaultAttr == DSA_private);
2458 if (DVarPrivate.CKind == OMPC_unknown)
2481 VD = cast<VarDecl>(VDPrivateRefExpr->
getDecl());
2482 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2485 if (DVarPrivate.CKind != OMPC_unknown ||
2486 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2487 DSAStack->getDefaultDSA() == DSA_private ||
2488 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2489 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2494void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2495 unsigned Level)
const {
2500 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2506 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2508 DSAStack->resetPossibleLoopCounter();
2514 unsigned CapLevel)
const {
2515 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2516 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2517 (!
DSAStack->isClauseParsingMode() ||
2518 DSAStack->getParentDirective() != OMPD_unknown)) {
2519 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2522 DefaultDataSharingAttributes DefaultAttr) {
2524 DefaultAttr == DSA_private;
2528 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(
D) &&
2529 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(
D)) &&
2530 !
DSAStack->isLoopControlVariable(
D).first)
2531 return OMPC_private;
2534 bool IsTriviallyCopyable =
2535 D->getType().getNonReferenceType().isTriviallyCopyableType(
2538 .getNonReferenceType()
2540 ->getAsCXXRecordDecl();
2545 (IsTriviallyCopyable ||
2551 return OMPC_firstprivate;
2552 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2553 if (DVar.CKind != OMPC_shared &&
2554 !
DSAStack->isLoopControlVariable(
D, Level).first && !DVar.RefExpr) {
2555 DSAStack->addImplicitTaskFirstprivate(Level,
D);
2556 return OMPC_firstprivate;
2565 return OMPC_private;
2568 DSAStack->isLoopControlVariable(
D).first) &&
2573 return OMPC_private;
2575 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2581 return OMPC_private;
2586 DSAStack->isUsesAllocatorsDecl(Level,
D).value_or(
2587 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2588 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2589 return OMPC_private;
2593 (
DSAStack->isClauseParsingMode() &&
2594 DSAStack->getClauseParsingMode() == OMPC_private) ||
2599 return K == OMPD_taskgroup ||
2600 ((isOpenMPParallelDirective(K) ||
2601 isOpenMPWorksharingDirective(K)) &&
2602 !isOpenMPSimdDirective(K));
2605 DSAStack->isTaskgroupReductionRef(
D, Level)))
2612 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2615 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2616 const unsigned NewLevel = I - 1;
2620 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2628 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2638 if (
DSAStack->mustBeFirstprivateAtLevel(
2640 OMPC = OMPC_firstprivate;
2644 if (OMPC != OMPC_unknown)
2646 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2650 unsigned CaptureLevel)
const {
2651 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2656 const auto *VD = dyn_cast<VarDecl>(
D);
2660 Regions[CaptureLevel] != OMPD_task;
2664 unsigned CaptureLevel)
const {
2665 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2668 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2672 DSAStackTy::DSAVarData TopDVar =
2674 unsigned NumLevels =
2679 return (NumLevels == CaptureLevel + 1 &&
2680 (TopDVar.CKind != OMPC_shared ||
2681 DSAStack->getDefaultDSA() == DSA_firstprivate));
2684 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2685 if (DVar.CKind != OMPC_shared)
2687 }
while (Level > 0);
2693void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2697 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2702 "Not in OpenMP declare variant scope!");
2704 OMPDeclareVariantScopes.pop_back();
2710 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2711 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2715 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2718 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2719 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2722 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2723 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2724 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2726 StringRef HostDevTy =
2728 Diag(
Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2729 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2730 diag::note_omp_marked_device_type_here)
2736 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2740 for (OMPDeclareVariantAttr *A :
2741 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2742 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2743 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2744 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2745 OMPDeclareTargetDeclAttr::getDeviceType(
2746 VariantFD->getMostRecentDecl());
2747 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2753 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2757 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2758 Diag(
Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2759 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2760 diag::note_omp_marked_device_type_here)
2778 DSAStack->setClauseParsingMode(OMPC_unknown);
2782static std::pair<ValueDecl *, bool>
2784 SourceRange &ERange,
bool AllowArraySection =
false,
2785 StringRef DiagType =
"");
2790 bool InscanFound =
false;
2797 if (
C->getClauseKind() != OMPC_reduction)
2799 auto *RC = cast<OMPReductionClause>(
C);
2800 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2802 InscanLoc = RC->getModifierLoc();
2805 if (RC->getModifier() == OMPC_REDUCTION_task) {
2815 S.
Diag(RC->getModifierLoc(),
2816 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2822 if (
C->getClauseKind() != OMPC_reduction)
2824 auto *RC = cast<OMPReductionClause>(
C);
2825 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2828 : RC->getModifierLoc(),
2829 diag::err_omp_inscan_reduction_expected);
2830 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2833 for (
Expr *Ref : RC->varlists()) {
2834 assert(Ref &&
"NULL expr in OpenMP nontemporal clause.");
2837 Expr *SimpleRefExpr = Ref;
2844 S.
Diag(Ref->getExprLoc(),
2845 diag::err_omp_reduction_not_inclusive_exclusive)
2846 << Ref->getSourceRange();
2860 const DSAStackTy::DSAVarData &DVar,
2861 bool IsLoopIterVar =
false);
2869 if (
const auto *
D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2871 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
2873 for (
Expr *DE : Clause->varlists()) {
2874 if (DE->isValueDependent() || DE->isTypeDependent()) {
2875 PrivateCopies.push_back(
nullptr);
2878 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2879 auto *VD = cast<VarDecl>(DRE->getDecl());
2881 const DSAStackTy::DSAVarData DVar =
2883 if (DVar.CKind == OMPC_lastprivate) {
2890 SemaRef, DE->getExprLoc(),
Type.getUnqualifiedType(),
2894 PrivateCopies.push_back(
nullptr);
2902 PrivateCopies.push_back(
nullptr);
2905 Clause->setPrivateCopies(PrivateCopies);
2909 if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
2911 for (
Expr *RefExpr : Clause->varlists()) {
2912 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
2915 Expr *SimpleRefExpr = RefExpr;
2919 PrivateRefs.push_back(RefExpr);
2924 const DSAStackTy::DSAVarData DVar =
2926 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2929 Clause->setPrivateRefs(PrivateRefs);
2932 if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
2933 for (
unsigned I = 0,
E = Clause->getNumberOfAllocators(); I <
E; ++I) {
2935 auto *DRE = dyn_cast<DeclRefExpr>(
D.Allocator->IgnoreParenImpCasts());
2939 if (!VD || !isa<VarDecl>(VD))
2941 DSAStackTy::DSAVarData DVar =
2947 Expr *MapExpr =
nullptr;
2949 DSAStack->checkMappableExprComponentListsForDecl(
2955 auto MI = MapExprComponents.rbegin();
2956 auto ME = MapExprComponents.rend();
2958 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2959 VD->getCanonicalDecl()) {
2960 MapExpr = MI->getAssociatedExpression();
2965 Diag(
D.Allocator->getExprLoc(),
2966 diag::err_omp_allocator_used_in_clauses)
2971 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2972 << MapExpr->getSourceRange();
2990 Expr *NumIterations,
Sema &SemaRef,
2991 Scope *S, DSAStackTy *Stack);
2995 DSAStackTy *Stack) {
2997 "loop exprs were not built");
3004 auto *LC = dyn_cast<OMPLinearClause>(
C);
3023 explicit VarDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3024 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3026 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3034 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3035 return std::make_unique<VarDeclFilterCCC>(*
this);
3044 explicit VarOrFuncDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3045 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3047 if (ND && ((isa<VarDecl>(ND) && ND->
getKind() == Decl::Var) ||
3048 isa<FunctionDecl>(ND))) {
3055 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3056 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3077 VarDeclFilterCCC CCC(
SemaRef);
3083 ? diag::err_undeclared_var_use_suggest
3084 : diag::err_omp_expected_var_arg_suggest)
3086 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3088 Diag(
Id.getLoc(), Lookup.
empty() ? diag::err_undeclared_var_use
3089 : diag::err_omp_expected_var_arg)
3094 Diag(
Id.getLoc(), diag::err_omp_expected_var_arg) <<
Id.getName();
3103 Diag(
Id.getLoc(), diag::err_omp_global_var_arg)
3108 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3120 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3121 << getOpenMPDirectiveName(Kind) << VD;
3125 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3135 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3136 << getOpenMPDirectiveName(Kind) << VD;
3140 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3152 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3153 << getOpenMPDirectiveName(Kind) << VD;
3157 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3166 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3167 << getOpenMPDirectiveName(Kind) << VD;
3171 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3179 if (Kind == OMPD_threadprivate && VD->
isUsed() &&
3181 Diag(
Id.getLoc(), diag::err_omp_var_used)
3182 << getOpenMPDirectiveName(Kind) << VD;
3204class LocalVarRefChecker final
3210 if (
const auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3213 diag::err_omp_local_var_in_threadprivate_init)
3215 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3222 bool VisitStmt(
const Stmt *S) {
3223 for (
const Stmt *Child : S->children()) {
3224 if (Child && Visit(Child))
3229 explicit LocalVarRefChecker(
Sema &SemaRef) : SemaRef(SemaRef) {}
3238 for (
Expr *RefExpr : VarList) {
3239 auto *DE = cast<DeclRefExpr>(RefExpr);
3240 auto *VD = cast<VarDecl>(DE->getDecl());
3257 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3264 Diag(ILoc, diag::err_omp_ref_type_arg)
3265 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->
getType();
3269 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3277 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3282 Diag(ILoc, diag::err_omp_var_thread_local)
3287 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3295 LocalVarRefChecker Checker(
SemaRef);
3296 if (Checker.Visit(
Init))
3300 Vars.push_back(RefExpr);
3301 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3302 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3305 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3308 if (!Vars.empty()) {
3316static OMPAllocateDeclAttr::AllocatorTypeTy
3319 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3320 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3321 Allocator->isInstantiationDependent() ||
3322 Allocator->containsUnexpandedParameterPack())
3323 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3324 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3325 llvm::FoldingSetNodeID AEId;
3326 const Expr *AE = Allocator->IgnoreParenImpCasts();
3328 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3329 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3330 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3331 llvm::FoldingSetNodeID DAEId;
3334 if (AEId == DAEId) {
3335 AllocatorKindRes = AllocatorKind;
3339 return AllocatorKindRes;
3344 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3345 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3347 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3348 Expr *PrevAllocator = A->getAllocator();
3349 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3351 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3352 if (AllocatorsMatch &&
3353 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3354 Allocator && PrevAllocator) {
3355 const Expr *AE = Allocator->IgnoreParenImpCasts();
3357 llvm::FoldingSetNodeID AEId, PAEId;
3360 AllocatorsMatch = AEId == PAEId;
3362 if (!AllocatorsMatch) {
3364 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3368 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3370 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3374 Allocator ? Allocator->getExprLoc() : RefExpr->
getExprLoc();
3376 Allocator ? Allocator->getSourceRange() : RefExpr->
getSourceRange();
3378 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3380 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3381 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3382 << (Allocator ? 1 : 0) << AllocatorStream.str()
3383 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3385 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3386 << PrevAllocatorRange;
3394 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3396 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3405 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3406 Allocator->isInstantiationDependent() ||
3407 Allocator->containsUnexpandedParameterPack()))
3409 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3410 Allocator, Alignment, SR);
3413 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3419 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3420 Expr *Alignment =
nullptr;
3421 Expr *Allocator =
nullptr;
3422 if (Clauses.empty()) {
3432 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3433 Allocator = AC->getAllocator();
3434 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3435 Alignment = AC->getAlignment();
3437 llvm_unreachable(
"Unexpected clause on allocate directive");
3439 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3442 for (
Expr *RefExpr : VarList) {
3443 auto *DE = cast<DeclRefExpr>(RefExpr);
3444 auto *VD = cast<VarDecl>(DE->getDecl());
3448 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3456 AllocatorKind, Allocator))
3464 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3465 Diag(Allocator->getExprLoc(),
3466 diag::err_omp_expected_predefined_allocator)
3467 << Allocator->getSourceRange();
3471 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3477 Vars.push_back(RefExpr);
3496 Diag(
Loc, diag::err_omp_invalid_scope) <<
"requires";
3510 bool SkippedClauses) {
3511 if (!SkippedClauses && Assumptions.empty())
3512 Diag(
Loc, diag::err_omp_no_clause_for_directive)
3513 << llvm::omp::getAllAssumeClauseOptions()
3514 << llvm::omp::getOpenMPDirectiveName(DKind);
3518 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3519 OMPAssumeScoped.push_back(AA);
3524 if (Assumptions.empty())
3527 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3528 "Unexpected omp assumption directive!");
3529 OMPAssumeGlobal.push_back(AA);
3537 while (Ctx->getLexicalParent())
3539 DeclContexts.push_back(Ctx);
3540 while (!DeclContexts.empty()) {
3542 for (
auto *SubDC : DC->
decls()) {
3543 if (SubDC->isInvalidDecl())
3545 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3546 DeclContexts.push_back(CTD->getTemplatedDecl());
3547 llvm::append_range(DeclContexts, CTD->specializations());
3550 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3551 DeclContexts.push_back(DC);
3552 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3562 OMPAssumeScoped.pop_back();
3572 DSAStack->getEncounteredTargetLocs();
3574 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3575 for (
const OMPClause *CNew : ClauseList) {
3577 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3578 isa<OMPUnifiedAddressClause>(CNew) ||
3579 isa<OMPReverseOffloadClause>(CNew) ||
3580 isa<OMPDynamicAllocatorsClause>(CNew)) {
3581 Diag(
Loc, diag::err_omp_directive_before_requires)
3582 <<
"target" << getOpenMPClauseName(CNew->getClauseKind());
3584 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3588 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3589 Diag(
Loc, diag::err_omp_directive_before_requires)
3590 <<
"atomic" << getOpenMPClauseName(CNew->getClauseKind());
3591 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3597 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3605 const DSAStackTy::DSAVarData &DVar,
3606 bool IsLoopIterVar) {
3608 SemaRef.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3609 << getOpenMPClauseName(DVar.CKind);
3613 PDSA_StaticMemberShared,
3614 PDSA_StaticLocalVarShared,
3615 PDSA_LoopIterVarPrivate,
3616 PDSA_LoopIterVarLinear,
3617 PDSA_LoopIterVarLastprivate,
3618 PDSA_ConstVarShared,
3619 PDSA_GlobalVarShared,
3620 PDSA_TaskVarFirstprivate,
3621 PDSA_LocalVarPrivate,
3623 } Reason = PDSA_Implicit;
3624 bool ReportHint =
false;
3626 auto *VD = dyn_cast<VarDecl>(
D);
3627 if (IsLoopIterVar) {
3628 if (DVar.CKind == OMPC_private)
3629 Reason = PDSA_LoopIterVarPrivate;
3630 else if (DVar.CKind == OMPC_lastprivate)
3631 Reason = PDSA_LoopIterVarLastprivate;
3633 Reason = PDSA_LoopIterVarLinear;
3635 DVar.CKind == OMPC_firstprivate) {
3636 Reason = PDSA_TaskVarFirstprivate;
3637 ReportLoc = DVar.ImplicitDSALoc;
3639 Reason = PDSA_StaticLocalVarShared;
3641 Reason = PDSA_StaticMemberShared;
3643 Reason = PDSA_GlobalVarShared;
3645 Reason = PDSA_ConstVarShared;
3646 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3648 Reason = PDSA_LocalVarPrivate;
3650 if (Reason != PDSA_Implicit) {
3651 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3652 << Reason << ReportHint
3653 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3654 }
else if (DVar.ImplicitDSALoc.isValid()) {
3655 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3656 << getOpenMPClauseName(DVar.CKind);
3662 bool IsAggregateOrDeclareTarget) {
3665 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3666 Kind = OMPC_MAP_alloc;
3668 case OMPC_DEFAULTMAP_MODIFIER_to:
3671 case OMPC_DEFAULTMAP_MODIFIER_from:
3672 Kind = OMPC_MAP_from;
3674 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3675 Kind = OMPC_MAP_tofrom;
3677 case OMPC_DEFAULTMAP_MODIFIER_present:
3683 Kind = OMPC_MAP_alloc;
3685 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3687 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3688 case OMPC_DEFAULTMAP_MODIFIER_none:
3689 case OMPC_DEFAULTMAP_MODIFIER_default:
3694 if (IsAggregateOrDeclareTarget) {
3695 Kind = OMPC_MAP_tofrom;
3698 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3705class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3708 bool ErrorFound =
false;
3709 bool TryCaptureCXXThisMembers =
false;
3716 ImplicitMapModifier[DefaultmapKindNum];
3718 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3722 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3724 if (S->getDirectiveKind() == OMPD_atomic ||
3725 S->getDirectiveKind() == OMPD_critical ||
3726 S->getDirectiveKind() == OMPD_section ||
3727 S->getDirectiveKind() == OMPD_master ||
3728 S->getDirectiveKind() == OMPD_masked ||
3729 S->getDirectiveKind() == OMPD_scope ||
3731 Visit(S->getAssociatedStmt());
3734 visitSubCaptures(S->getInnermostCapturedStmt());
3737 if (TryCaptureCXXThisMembers ||
3739 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3741 return C.capturesThis();
3743 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3744 TryCaptureCXXThisMembers =
true;
3745 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3746 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3753 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
3754 for (
Expr *Ref : FC->varlists())
3767 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3770 !Stack->getTopDSA(VD,
false).RefExpr &&
3771 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3772 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3773 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3774 Visit(CED->getInit());
3777 }
else if (VD->
isImplicit() || isa<OMPCapturedExprDecl>(VD))
3780 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3785 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3786 !Stack->isImplicitTaskFirstprivate(VD))
3789 if (Stack->isUsesAllocatorsDecl(VD))
3792 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
3794 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3798 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3799 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3802 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3803 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3804 !Stack->isImplicitTaskFirstprivate(VD))
3813 if (DVar.CKind == OMPC_unknown &&
3814 (Stack->getDefaultDSA() == DSA_none ||
3815 Stack->getDefaultDSA() == DSA_private ||
3816 Stack->getDefaultDSA() == DSA_firstprivate) &&
3817 isImplicitOrExplicitTaskingRegion(DKind) &&
3818 VarsWithInheritedDSA.count(VD) == 0) {
3819 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3820 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3821 Stack->getDefaultDSA() == DSA_private)) {
3822 DSAStackTy::DSAVarData DVar =
3823 Stack->getImplicitDSA(VD,
false);
3824 InheritedDSA = DVar.CKind == OMPC_unknown;
3827 VarsWithInheritedDSA[VD] =
E;
3828 if (Stack->getDefaultDSA() == DSA_none)
3843 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3844 OMPC_DEFAULTMAP_MODIFIER_none;
3845 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3846 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3850 if (!Stack->checkMappableExprComponentListsForDecl(
3855 auto MI = MapExprComponents.rbegin();
3856 auto ME = MapExprComponents.rend();
3857 return MI != ME && MI->getAssociatedDeclaration() == VD;
3859 VarsWithInheritedDSA[VD] =
E;
3865 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3866 OMPC_DEFAULTMAP_MODIFIER_present;
3867 if (IsModifierPresent) {
3868 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3869 OMPC_MAP_MODIFIER_present)) {
3870 ImplicitMapModifier[ClauseKind].push_back(
3871 OMPC_MAP_MODIFIER_present);
3877 !Stack->isLoopControlVariable(VD).first) {
3878 if (!Stack->checkMappableExprComponentListsForDecl(
3883 if (SemaRef.LangOpts.OpenMP >= 50)
3884 return !StackComponents.empty();
3887 return StackComponents.size() == 1 ||
3889 llvm::drop_begin(llvm::reverse(StackComponents)),
3890 [](const OMPClauseMappableExprCommon::
3891 MappableComponent &MC) {
3892 return MC.getAssociatedDeclaration() ==
3894 (isa<ArraySectionExpr>(
3895 MC.getAssociatedExpression()) ||
3896 isa<OMPArrayShapingExpr>(
3897 MC.getAssociatedExpression()) ||
3898 isa<ArraySubscriptExpr>(
3899 MC.getAssociatedExpression()));
3902 bool IsFirstprivate =
false;
3904 if (
const auto *RD =
3906 IsFirstprivate = RD->isLambda();
3908 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3909 if (IsFirstprivate) {
3910 ImplicitFirstprivate.emplace_back(
E);
3913 Stack->getDefaultmapModifier(ClauseKind);
3915 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3916 ImplicitMap[ClauseKind][
Kind].emplace_back(
E);
3926 DVar = Stack->hasInnermostDSA(
3929 return C == OMPC_reduction && !AppliedToPointee;
3938 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
3944 DVar = Stack->getImplicitDSA(VD,
false);
3946 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3947 DVar.CKind == OMPC_firstprivate) ||
3948 (Stack->getDefaultDSA() == DSA_private &&
3949 DVar.CKind == OMPC_private)) &&
3951 !Stack->isLoopControlVariable(VD).first) {
3952 if (Stack->getDefaultDSA() == DSA_private)
3953 ImplicitPrivate.push_back(
E);
3955 ImplicitFirstprivate.push_back(
E);
3962 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3963 Stack->addToParentTargetRegionLinkGlobals(
E);
3972 auto *FD = dyn_cast<FieldDecl>(
E->getMemberDecl());
3977 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
3980 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3984 !Stack->isLoopControlVariable(FD).first &&
3985 !Stack->checkMappableExprComponentListsForDecl(
3990 return isa<CXXThisExpr>(
3992 StackComponents.back().getAssociatedExpression())
4004 if (Stack->isClassPreviouslyMapped(TE->getType()))
4008 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4013 ImplicitMap[ClauseKind][
Kind].emplace_back(
E);
4022 DVar = Stack->hasInnermostDSA(
4025 return C == OMPC_reduction && !AppliedToPointee;
4034 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4040 DVar = Stack->getImplicitDSA(FD,
false);
4042 !Stack->isLoopControlVariable(FD).first) {
4047 if (DVar.CKind != OMPC_unknown)
4048 ImplicitFirstprivate.push_back(
E);
4055 Stack->getCurrentDirective(),
4058 const auto *VD = cast<ValueDecl>(
4059 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4060 if (!Stack->checkMappableExprComponentListsForDecl(
4066 auto CCI = CurComponents.rbegin();
4067 auto CCE = CurComponents.rend();
4068 for (const auto &SC : llvm::reverse(StackComponents)) {
4070 if (CCI->getAssociatedExpression()->getStmtClass() !=
4071 SC.getAssociatedExpression()->getStmtClass())
4072 if (!((isa<ArraySectionExpr>(
4073 SC.getAssociatedExpression()) ||
4074 isa<OMPArrayShapingExpr>(
4075 SC.getAssociatedExpression())) &&
4076 isa<ArraySubscriptExpr>(
4077 CCI->getAssociatedExpression())))
4080 const Decl *CCD = CCI->getAssociatedDeclaration();
4081 const Decl *SCD = SC.getAssociatedDeclaration();
4082 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4083 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4086 std::advance(CCI, 1);
4092 Visit(
E->getBase());
4094 }
else if (!TryCaptureCXXThisMembers) {
4095 Visit(
E->getBase());
4102 if (isa_and_nonnull<OMPPrivateClause>(
C))
4108 if (
C && !((isa<OMPFirstprivateClause>(
C) || isa<OMPMapClause>(
C)) &&
4111 for (
Stmt *CC :
C->children()) {
4118 VisitSubCaptures(S);
4127 for (
Stmt *
C : S->arguments()) {
4134 if (
Expr *Callee = S->getCallee()) {
4135 auto *CI =
Callee->IgnoreParenImpCasts();
4136 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4137 Visit(CE->getBase());
4138 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4142 void VisitStmt(
Stmt *S) {
4143 for (
Stmt *
C : S->children()) {
4154 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4156 VarDecl *VD = Cap.getCapturedVar();
4160 Stack->checkMappableExprComponentListsForDecl(
4167 Cap.getLocation(),
true);
4171 bool isErrorFound()
const {
return ErrorFound; }
4173 return ImplicitFirstprivate;
4178 return ImplicitMap[DK][MK];
4182 return ImplicitMapModifier[
Kind];
4185 return VarsWithInheritedDSA;
4189 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4204 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4206 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4208 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4210 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4212 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4213 Stack->handleConstructTrait(Traits, ScopeEntry);
4224 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4225 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4227 if (LoopBoundSharing) {
4229 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4230 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4234 Params.push_back(std::make_pair(StringRef(),
QualType()));
4255 std::make_pair(
".global_tid.", KmpInt32Ty),
4256 std::make_pair(
".part_id.", KmpInt32PtrTy),
4257 std::make_pair(
".privates.", VoidPtrTy),
4262 std::make_pair(StringRef(),
QualType())
4273 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4276 Params.push_back(std::make_pair(StringRef(),
QualType()));
4283 std::make_pair(StringRef(),
QualType())
4305 std::make_pair(
".global_tid.", KmpInt32Ty),
4306 std::make_pair(
".part_id.", KmpInt32PtrTy),
4307 std::make_pair(
".privates.", VoidPtrTy),
4312 std::make_pair(
".lb.", KmpUInt64Ty),
4313 std::make_pair(
".ub.", KmpUInt64Ty),
4314 std::make_pair(
".st.", KmpInt64Ty),
4315 std::make_pair(
".liter.", KmpInt32Ty),
4316 std::make_pair(
".reductions.", VoidPtrTy),
4317 std::make_pair(StringRef(),
QualType())
4330 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4331 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4334 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4369 case OMPD_metadirective:
4372 llvm_unreachable(
"Unexpected capture region");
4388 case OMPD_interchange:
4400int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4407 return CaptureRegions.size();
4411 Expr *CaptureExpr,
bool WithInit,
4413 bool AsExpression) {
4414 assert(CaptureExpr);
4420 Ty =
C.getLValueReferenceType(Ty);
4422 Ty =
C.getPointerType(Ty);
4434 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4445 CD = cast<OMPCapturedExprDecl>(VD);
4484class CaptureRegionUnwinderRAII {
4491 CaptureRegionUnwinderRAII(
Sema &S,
bool &ErrorFound,
4493 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4494 ~CaptureRegionUnwinderRAII() {
4497 while (--ThisCaptureLevel >= 0)
4510 DSAStack->getCurrentDirective()))) {
4512 if (
const auto *RD =
Type.getCanonicalType()
4513 .getNonReferenceType()
4515 bool SavedForceCaptureByReferenceInTargetExecutable =
4516 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4517 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4519 if (RD->isLambda()) {
4520 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4522 RD->getCaptureFields(Captures, ThisCapture);
4525 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4530 }
else if (LC.getCaptureKind() ==
LCK_This) {
4533 ThisTy, ThisCapture->
getType()))
4538 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4539 SavedForceCaptureByReferenceInTargetExecutable);
4549 for (
const OMPClause *Clause : Clauses) {
4551 Ordered = cast<OMPOrderedClause>(Clause);
4553 Order = cast<OMPOrderClause>(Clause);
4554 if (Order->
getKind() != OMPC_ORDER_concurrent)
4557 if (Ordered && Order)
4561 if (Ordered && Order) {
4563 diag::err_omp_simple_clause_incompatible_with_ordered)
4564 << getOpenMPClauseName(OMPC_order)
4581 bool ErrorFound =
false;
4582 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4584 if (!S.isUsable()) {
4599 DSAStack->getCurrentDirective() == OMPD_target) &&
4603 auto *IRC = cast<OMPInReductionClause>(Clause);
4604 for (
Expr *
E : IRC->taskgroup_descriptors())
4616 if (
auto *
E = cast_or_null<Expr>(VarRef)) {
4620 DSAStack->setForceVarCapturing(
false);
4621 }
else if (CaptureRegions.size() > 1 ||
4622 CaptureRegions.back() != OMPD_unknown) {
4626 if (
Expr *
E =
C->getPostUpdateExpr())
4631 SC = cast<OMPScheduleClause>(Clause);
4633 OC = cast<OMPOrderedClause>(Clause);
4635 LCs.push_back(cast<OMPLinearClause>(Clause));
4646 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4651 diag::err_omp_simple_clause_incompatible_with_ordered)
4652 << getOpenMPClauseName(OMPC_schedule)
4654 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4665 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4674 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
4681 unsigned CompletedRegions = 0;
4686 if (ThisCaptureRegion != OMPD_unknown) {
4694 if (CaptureRegion == ThisCaptureRegion ||
4695 CaptureRegion == OMPD_unknown) {
4696 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4697 for (
Decl *
D : DS->decls())
4704 if (ThisCaptureRegion == OMPD_target) {
4708 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4709 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4712 if (
Expr *
E =
D.AllocatorTraits)
4719 if (ThisCaptureRegion == OMPD_parallel) {
4723 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4724 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4726 for (
Expr *
E : RC->copy_array_temps())
4730 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4731 for (
Expr *
E : AC->varlists())
4736 if (++CompletedRegions == CaptureRegions.size())
4747 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4750 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4751 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4754 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4755 << getOpenMPDirectiveName(CancelRegion);
4765 if (!Stack->getCurScope())
4770 bool NestingProhibited =
false;
4771 bool CloseNesting =
true;
4772 bool OrphanSeen =
false;
4775 ShouldBeInParallelRegion,
4776 ShouldBeInOrderedRegion,
4777 ShouldBeInTargetRegion,
4778 ShouldBeInTeamsRegion,
4779 ShouldBeInLoopSimdRegion,
4780 } Recommend = NoRecommend;
4784 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4787 if (SemaRef.
LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4788 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4789 CurrentRegion != OMPD_parallel &&
4791 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
4792 << getOpenMPDirectiveName(CurrentRegion);
4796 ((SemaRef.
LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4797 (SemaRef.
LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4798 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4799 CurrentRegion != OMPD_scan))) {
4812 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
4813 ? diag::err_omp_prohibited_region_simd
4814 : diag::warn_omp_nesting_simd)
4815 << (SemaRef.
LangOpts.OpenMP >= 50 ? 1 : 0);
4816 return CurrentRegion != OMPD_simd;
4818 if (EnclosingConstruct == OMPD_atomic) {
4821 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4824 if (CurrentRegion == OMPD_section) {
4829 if (EnclosingConstruct != OMPD_sections) {
4830 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4831 << (ParentRegion != OMPD_unknown)
4832 << getOpenMPDirectiveName(ParentRegion);
4840 if (ParentRegion == OMPD_unknown &&
4842 CurrentRegion != OMPD_cancellation_point &&
4843 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4847 if (SemaRef.
LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4848 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4850 EnclosingConstruct == OMPD_loop)) {
4851 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4852 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
4853 <<
true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4854 << getOpenMPDirectiveName(CurrentRegion);
4857 if (CurrentRegion == OMPD_cancellation_point ||
4858 CurrentRegion == OMPD_cancel) {
4871 if (CancelRegion == OMPD_taskgroup) {
4872 NestingProhibited = EnclosingConstruct != OMPD_task &&
4874 EnclosingConstruct != OMPD_taskloop);
4875 }
else if (CancelRegion == OMPD_sections) {
4876 NestingProhibited = EnclosingConstruct != OMPD_section &&
4877 EnclosingConstruct != OMPD_sections;
4879 NestingProhibited = CancelRegion != Leafs.back();
4881 OrphanSeen = ParentRegion == OMPD_unknown;
4882 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4889 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
4895 bool DeadLock = Stack->hasDirective(
4899 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
4900 PreviousCriticalLoc = Loc;
4907 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4909 if (PreviousCriticalLoc.
isValid())
4910 SemaRef.
Diag(PreviousCriticalLoc,
4911 diag::note_omp_previous_critical_region);
4914 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4924 llvm::is_contained({OMPD_masked, OMPD_master,
4925 OMPD_critical, OMPD_ordered},
4926 EnclosingConstruct);
4937 llvm::is_contained({OMPD_masked, OMPD_master,
4938 OMPD_critical, OMPD_ordered},
4939 EnclosingConstruct);
4940 Recommend = ShouldBeInParallelRegion;
4941 }
else if (CurrentRegion == OMPD_ordered) {
4950 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4953 Stack->isParentOrderedRegion());
4954 Recommend = ShouldBeInOrderedRegion;
4960 (SemaRef.
LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4961 (SemaRef.
LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4962 EnclosingConstruct != OMPD_target);
4963 OrphanSeen = ParentRegion == OMPD_unknown;
4964 Recommend = ShouldBeInTargetRegion;
4965 }
else if (CurrentRegion == OMPD_scan) {
4966 if (SemaRef.
LangOpts.OpenMP >= 50) {
4971 NestingProhibited = !llvm::is_contained(
4972 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4974 NestingProhibited =
true;
4976 OrphanSeen = ParentRegion == OMPD_unknown;
4977 Recommend = ShouldBeInLoopSimdRegion;
4981 EnclosingConstruct == OMPD_teams) {
4993 CurrentRegion != OMPD_loop &&
4995 CurrentRegion == OMPD_atomic);
4996 Recommend = ShouldBeInParallelRegion;
4998 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5004 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5005 Recommend = ShouldBeInTeamsRegion;
5011 NestingProhibited = EnclosingConstruct != OMPD_teams;
5012 Recommend = ShouldBeInTeamsRegion;
5014 if (!NestingProhibited &&
5021 NestingProhibited = Stack->hasDirective(
5025 OffendingRegion = K;
5031 CloseNesting =
false;
5033 if (NestingProhibited) {
5035 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5036 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5038 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5039 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5040 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5054 bool ErrorFound =
false;
5055 unsigned NamedModifiersNumber = 0;
5056 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5057 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5060 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5064 if (FoundNameModifiers[CurNM]) {
5065 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5066 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5067 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5069 }
else if (CurNM != OMPD_unknown) {
5070 NameModifierLoc.push_back(IC->getNameModifierLoc());
5071 ++NamedModifiersNumber;
5073 FoundNameModifiers[CurNM] = IC;
5074 if (CurNM == OMPD_unknown)
5080 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5081 S.
Diag(IC->getNameModifierLoc(),
5082 diag::err_omp_wrong_if_directive_name_modifier)
5083 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5090 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5091 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5092 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5093 diag::err_omp_no_more_if_clause);
5096 std::string Sep(
", ");
5097 unsigned AllowedCnt = 0;
5098 unsigned TotalAllowedNum =
5099 AllowedNameModifiers.size() - NamedModifiersNumber;
5100 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5103 if (!FoundNameModifiers[NM]) {
5105 Values += getOpenMPDirectiveName(NM);
5107 if (AllowedCnt + 2 == TotalAllowedNum)
5109 else if (AllowedCnt + 1 != TotalAllowedNum)
5114 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5115 diag::err_omp_unnamed_if_clause)
5116 << (TotalAllowedNum > 1) << Values;
5119 S.
Diag(
Loc, diag::note_omp_previous_named_if_clause);
5129 bool AllowArraySection,
5130 StringRef DiagType) {
5133 return std::make_pair(
nullptr,
true);
5145 } IsArrayExpr = NoArrayExpr;
5146 if (AllowArraySection) {
5147 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5148 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5149 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5150 Base = TempASE->getBase()->IgnoreParenImpCasts();
5152 IsArrayExpr = ArraySubscript;
5153 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5154 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5155 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5156 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5157 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5158 Base = TempASE->getBase()->IgnoreParenImpCasts();
5160 IsArrayExpr = OMPArraySection;
5166 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5167 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5168 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5170 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5171 !isa<FieldDecl>(ME->getMemberDecl()))) {
5172 if (IsArrayExpr != NoArrayExpr) {
5173 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5174 << IsArrayExpr << ERange;
5175 }
else if (!DiagType.empty()) {
5179 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5180 << DiagSelect << DiagType << ERange;
5184 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5185 : diag::err_omp_expected_var_name_member_expr)
5188 return std::make_pair(
nullptr,
false);
5190 return std::make_pair(
5197class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5198 DSAStackTy *S =
nullptr;
5202 return S->isUsesAllocatorsDecl(
E->getDecl())
5203 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5204 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5206 bool VisitStmt(
const Stmt *S) {
5207 for (
const Stmt *Child : S->children()) {
5208 if (Child && Visit(Child))
5213 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5220 "Expected non-dependent context.");
5221 auto AllocateRange =
5224 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5229 if (
Cl->getClauseKind() == OMPC_private) {
5230 auto *PC = cast<OMPPrivateClause>(
Cl);
5231 I = PC->private_copies().begin();
5232 It = PC->varlist_begin();
5233 Et = PC->varlist_end();
5234 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5235 auto *PC = cast<OMPFirstprivateClause>(
Cl);
5236 I = PC->private_copies().begin();
5237 It = PC->varlist_begin();
5238 Et = PC->varlist_end();
5239 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5240 auto *PC = cast<OMPLastprivateClause>(
Cl);
5241 I = PC->private_copies().begin();
5242 It = PC->varlist_begin();
5243 Et = PC->varlist_end();
5244 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5245 auto *PC = cast<OMPLinearClause>(
Cl);
5246 I = PC->privates().begin();
5247 It = PC->varlist_begin();
5248 Et = PC->varlist_end();
5249 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5250 auto *PC = cast<OMPReductionClause>(
Cl);
5251 I = PC->privates().begin();
5252 It = PC->varlist_begin();
5253 Et = PC->varlist_end();
5254 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5255 auto *PC = cast<OMPTaskReductionClause>(
Cl);
5256 I = PC->privates().begin();
5257 It = PC->varlist_begin();
5258 Et = PC->varlist_end();
5259 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5260 auto *PC = cast<OMPInReductionClause>(
Cl);
5261 I = PC->privates().begin();
5262 It = PC->varlist_begin();
5263 Et = PC->varlist_end();
5265 llvm_unreachable(
"Expected private clause.");
5267 for (
Expr *
E : llvm::make_range(It, Et)) {
5274 Expr *SimpleRefExpr =
E;
5277 DeclToCopy.try_emplace(Res.first,
5278 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5283 auto *AC = cast<OMPAllocateClause>(
C);
5287 AC->getAllocator()) {
5288 Expr *Allocator = AC->getAllocator();
5294 AllocatorChecker Checker(Stack);
5295 if (Checker.Visit(Allocator))
5296 S.
Diag(Allocator->getExprLoc(),
5297 diag::err_omp_allocator_not_in_uses_allocators)
5298 << Allocator->getSourceRange();
5300 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5306 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5309 S.
Diag(AC->getAllocator()->getExprLoc(),
5310 diag::warn_omp_allocate_thread_on_task_target_directive)
5311 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5313 for (
Expr *
E : AC->varlists()) {
5316 Expr *SimpleRefExpr =
E;
5319 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5322 diag::err_omp_expected_private_copy_for_allocate);
5325 VarDecl *PrivateVD = DeclToCopy[VD];
5327 AllocatorKind, AC->getAllocator()))
5330 Expr *Alignment =
nullptr;
5347 CaptureVars(
Sema &Actions) : BaseTransform(Actions) {}
5349 bool AlwaysRebuild() {
return true; }
5362 BodyStmts.push_back(NewDeclStmt);
5400 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5411 auto BuildVarRef = [&](
VarDecl *VD) {
5416 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5418 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5424 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5428 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5432 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5436 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5440 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5442 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5446 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5448 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5449 "Expected one of these relational operators");
5456 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5460 if (Rel == BO_GE || Rel == BO_GT)
5462 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5465 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5471 if (Rel == BO_LE || Rel == BO_GE) {
5483 Expr *Divisor = BuildVarRef(NewStep);
5484 if (Rel == BO_GE || Rel == BO_GT)
5487 Expr *DivisorMinusOne =
5492 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5502 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5503 BodyStmts.push_back(ResultAssign);
5508 return cast<CapturedStmt>(
5535 {
"Logical", LogicalTy},
5546 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5551 auto *CS = cast<CapturedDecl>(Actions.
CurContext);
5555 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5558 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5561 CaptureVars Recap(Actions);
5566 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5581 BO_Assign, TargetRef, Advanced));
5583 return cast<CapturedStmt>(
5594 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5596 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5598 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5599 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5601 assert(LCAssign->getOpcode() == BO_Assign &&
5602 "init part must be a loop variable assignment");
5603 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5604 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5606 llvm_unreachable(
"Cannot determine loop variable");
5609 Cond = For->getCond();
5610 Inc = For->getInc();
5611 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5612 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5614 LUVDecl = RangeFor->getLoopVariable();
5616 Cond = RangeFor->getCond();
5617 Inc = RangeFor->getInc();
5619 llvm_unreachable(
"unhandled kind of loop");
5628 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5629 LHS = CondBinExpr->getLHS();
5630 RHS = CondBinExpr->getRHS();
5631 CondRel = CondBinExpr->getOpcode();
5632 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5633 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5634 LHS = CondCXXOp->getArg(0);
5635 RHS = CondCXXOp->getArg(1);
5636 switch (CondCXXOp->getOperator()) {
5637 case OO_ExclaimEqual:
5649 case OO_GreaterEqual:
5653 llvm_unreachable(
"unexpected iterator operator");
5656 llvm_unreachable(
"unexpected loop condition");
5660 cast<DeclRefExpr>(LHS->
IgnoreImplicit())->getDecl() != LIVDecl) {
5661 std::swap(LHS, RHS);
5678 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5680 switch (IncUn->getOpcode()) {
5690 llvm_unreachable(
"unhandled unary increment operator");
5693 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction), LogicalTy, {});
5694 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5695 if (IncBin->getOpcode() == BO_AddAssign) {
5696 Step = IncBin->getRHS();
5697 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5701 llvm_unreachable(
"unhandled binary increment operator");
5702 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5703 switch (CondCXXOp->getOperator()) {
5706 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5710 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5713 Step = CondCXXOp->getArg(1);
5720 llvm_unreachable(
"unhandled overloaded increment operator");
5723 llvm_unreachable(
"unknown increment expression");
5728 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5731 nullptr,
nullptr, {},
nullptr);
5733 LoopVarFunc, LVRef);
5738 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5745 "Loop transformation directive expected");
5746 return LoopTransform;
5753 Expr *UnresolvedMapper);
5765 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5766 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5770 auto *MI =
C->mapperlist_begin();
5771 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
5791 ElemType = ATy->getElementType();
5794 CanonType = ElemType;
5799 1, {CanonType,
nullptr});
5800 llvm::DenseMap<const Type *, Expr *>
Visited;
5803 while (!Types.empty()) {
5806 std::tie(BaseType, CurFD) = Types.pop_back_val();
5807 while (ParentChain.back().second == 0)
5808 ParentChain.pop_back();
5809 --ParentChain.back().second;
5825 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5836 Expr *BaseExpr = OE;
5837 for (
const auto &
P : ParentChain) {
5855 SubExprs.push_back(BaseExpr);
5859 bool FirstIter =
true;
5869 ParentChain.emplace_back(CurFD, 1);
5871 ++ParentChain.back().second;
5873 Types.emplace_back(FieldTy, FD);
5877 if (SubExprs.empty())
5882 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
5883 MapperIdScopeSpec, MapperId,
C->getMapType(),
5886 Clauses.push_back(NewClause);
5901 if (
D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5903 if (
C->getBindKind() == OMPC_BIND_parallel) {
5904 TeamsLoopCanBeParallelFor =
false;
5909 for (
const Stmt *Child :
D->children())
5919 bool IsOpenMPAPI =
false;
5920 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
5922 std::string Name = FD->getNameInfo().getAsString();
5923 IsOpenMPAPI = Name.find(
"omp_") == 0;
5925 TeamsLoopCanBeParallelFor =
5926 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5927 if (!TeamsLoopCanBeParallelFor)
5930 for (
const Stmt *Child :
C->children())
5938 Visit(S->getCapturedDecl()->getBody());
5941 void VisitStmt(
const Stmt *S) {
5944 for (
const Stmt *Child : S->children())
5948 explicit TeamsLoopChecker(
Sema &SemaRef)
5949 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
5952 bool TeamsLoopCanBeParallelFor;
5957 TeamsLoopChecker Checker(SemaRef);
5958 Checker.Visit(AStmt);
5959 return Checker.teamsLoopCanBeParallelFor();
5973 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5974 BindKind = BC->getBindKind();
5986 BindKind = OMPC_BIND_thread;
5988 getLeafConstructsOrSelf(ParentDirective);
5990 if (ParentDirective == OMPD_unknown) {
5992 diag::err_omp_bind_required_on_loop);
5993 }
else if (ParentLeafs.back() == OMPD_parallel) {
5994 BindKind = OMPC_BIND_parallel;
5995 }
else if (ParentLeafs.back() == OMPD_teams) {
5996 BindKind = OMPC_BIND_teams;
6004 ClausesWithImplicit.push_back(
C);
6008 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6010 if (
C->getClauseKind() == OMPC_reduction)
6012 diag::err_omp_loop_reduction_clause);
6019 BindKind, StartLoc)) {
6026 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6029 bool ErrorFound =
false;
6030 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6034 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
6037 DSAAttrChecker DSAChecker(
DSAStack,
SemaRef, cast<CapturedStmt>(AStmt));
6040 while (--ThisCaptureLevel >= 0)
6041 S = cast<CapturedStmt>(S)->getCapturedStmt();
6042 DSAChecker.Visit(S);
6046 auto *CS = cast<CapturedStmt>(AStmt);
6050 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6052 DSAChecker.visitSubCaptures(CS);
6054 if (DSAChecker.isErrorFound())
6057 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6060 DSAChecker.getImplicitFirstprivate().begin(),
6061 DSAChecker.getImplicitFirstprivate().end());
6063 DSAChecker.getImplicitPrivate().begin(),
6064 DSAChecker.getImplicitPrivate().end());
6068 ImplicitMapModifiers[DefaultmapKindNum];
6070 ImplicitMapModifiersLoc[DefaultmapKindNum];
6074 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6075 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6076 PresentModifierLocs[DMC->getDefaultmapKind()] =
6077 DMC->getDefaultmapModifierLoc();
6079 for (
unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6081 for (
unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6084 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6087 DSAChecker.getImplicitMapModifier(K);
6088 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6089 ImplicitModifier.end());
6090 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6091 ImplicitModifier.size(), PresentModifierLocs[VC]);
6095 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6096 for (
Expr *
E : IRC->taskgroup_descriptors())
6098 ImplicitFirstprivates.emplace_back(
E);
6103 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6104 ImplicitFirstprivates.push_back(DC->getEventHandler());
6106 if (!ImplicitFirstprivates.empty()) {
6110 ClausesWithImplicit.push_back(
Implicit);
6111 ErrorFound = cast<OMPFirstprivateClause>(
Implicit)->varlist_size() !=
6112 ImplicitFirstprivates.size();
6117 if (!ImplicitPrivates.empty()) {
6121 ClausesWithImplicit.push_back(
Implicit);
6122 ErrorFound = cast<OMPPrivateClause>(
Implicit)->varlist_size() !=
6123 ImplicitPrivates.size();
6132 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6136 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6137 for (
Expr *
E : RC->varlists())
6139 ImplicitExprs.emplace_back(
E);
6141 if (!ImplicitExprs.empty()) {
6147 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6150 ClausesWithImplicit.emplace_back(
Implicit);
6153 for (
unsigned I = 0,
E = DefaultmapKindNum; I <
E; ++I) {
6154 int ClauseKindCnt = -1;
6157 if (ImplicitMap.empty())
6163 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6164 MapperIdScopeSpec, MapperId, K,
true,
6167 ClausesWithImplicit.emplace_back(
Implicit);
6168 ErrorFound |= cast<OMPMapClause>(
Implicit)->varlist_size() !=
6179 ClausesWithImplicit);
6189 VarsWithInheritedDSA);
6200 assert(ClausesWithImplicit.empty() &&
6201 "reverse directive does not support any clauses");
6204 case OMPD_interchange:
6210 VarsWithInheritedDSA);
6214 EndLoc, VarsWithInheritedDSA);
6221 assert(ClausesWithImplicit.empty() &&
6222 "No clauses are allowed for 'omp section' directive");
6230 assert(ClausesWithImplicit.empty() &&
6231 "No clauses are allowed for 'omp master' directive");
6242 case OMPD_parallel_for:
6244 EndLoc, VarsWithInheritedDSA);
6246 case OMPD_parallel_for_simd:
6248 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6254 case OMPD_parallel_master:
6258 case OMPD_parallel_masked:
6262 case OMPD_parallel_sections:
6270 case OMPD_taskyield:
6271 assert(ClausesWithImplicit.empty() &&
6272 "No clauses are allowed for 'omp taskyield' directive");
6273 assert(AStmt ==
nullptr &&
6274 "No associated statement allowed for 'omp taskyield' directive");
6278 assert(AStmt ==
nullptr &&
6279 "No associated statement allowed for 'omp error' directive");
6283 assert(ClausesWithImplicit.empty() &&
6284 "No clauses are allowed for 'omp barrier' directive");
6285 assert(AStmt ==
nullptr &&
6286 "No associated statement allowed for 'omp barrier' directive");
6290 assert(AStmt ==
nullptr &&
6291 "No associated statement allowed for 'omp taskwait' directive");
6294 case OMPD_taskgroup:
6299 assert(AStmt ==
nullptr &&
6300 "No associated statement allowed for 'omp flush' directive");
6304 assert(AStmt ==
nullptr &&
6305 "No associated statement allowed for 'omp depobj' directive");
6309 assert(AStmt ==
nullptr &&
6310 "No associated statement allowed for 'omp scan' directive");
6329 case OMPD_target_parallel:
6333 case OMPD_target_parallel_for:
6335 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6337 case OMPD_cancellation_point:
6338 assert(ClausesWithImplicit.empty() &&
6339 "No clauses are allowed for 'omp cancellation point' directive");
6340 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6341 "cancellation point' directive");
6345 assert(AStmt ==
nullptr &&
6346 "No associated statement allowed for 'omp cancel' directive");
6350 case OMPD_target_data:
6354 case OMPD_target_enter_data:
6358 case OMPD_target_exit_data:
6364 EndLoc, VarsWithInheritedDSA);
6366 case OMPD_taskloop_simd:
6368 EndLoc, VarsWithInheritedDSA);
6370 case OMPD_master_taskloop:
6372 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6374 case OMPD_masked_taskloop:
6376 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6378 case OMPD_master_taskloop_simd:
6380 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6382 case OMPD_masked_taskloop_simd:
6384 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6386 case OMPD_parallel_master_taskloop:
6388 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6390 case OMPD_parallel_masked_taskloop:
6392 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6394 case OMPD_parallel_master_taskloop_simd:
6396 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6398 case OMPD_parallel_masked_taskloop_simd:
6400 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6402 case OMPD_distribute:
6404 EndLoc, VarsWithInheritedDSA);
6406 case OMPD_target_update:
6410 case OMPD_distribute_parallel_for:
6412 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6414 case OMPD_distribute_parallel_for_simd:
6416 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6418 case OMPD_distribute_simd:
6420 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6422 case OMPD_target_parallel_for_simd:
6424 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6426 case OMPD_target_simd:
6428 EndLoc, VarsWithInheritedDSA);
6430 case OMPD_teams_distribute:
6432 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6434 case OMPD_teams_distribute_simd:
6436 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6438 case OMPD_teams_distribute_parallel_for_simd:
6440 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6442 case OMPD_teams_distribute_parallel_for:
6444 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6446 case OMPD_target_teams:
6450 case OMPD_target_teams_distribute:
6452 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6454 case OMPD_target_teams_distribute_parallel_for:
6456 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6458 case OMPD_target_teams_distribute_parallel_for_simd:
6460 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6462 case OMPD_target_teams_distribute_simd:
6464 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6467 assert(AStmt ==
nullptr &&
6468 "No associated statement allowed for 'omp interop' directive");
6477 EndLoc, VarsWithInheritedDSA);
6479 case OMPD_teams_loop:
6481 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6483 case OMPD_target_teams_loop:
6485 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6487 case OMPD_parallel_loop:
6489 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6491 case OMPD_target_parallel_loop:
6493 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6495 case OMPD_declare_target:
6496 case OMPD_end_declare_target:
6497 case OMPD_threadprivate:
6499 case OMPD_declare_reduction:
6500 case OMPD_declare_mapper:
6501 case OMPD_declare_simd:
6503 case OMPD_declare_variant:
6504 case OMPD_begin_declare_variant:
6505 case OMPD_end_declare_variant:
6506 llvm_unreachable(
"OpenMP Directive is not allowed");
6509 llvm_unreachable(
"Unknown OpenMP directive");
6512 ErrorFound = Res.
isInvalid() || ErrorFound;
6516 if (
DSAStack->getDefaultDSA() == DSA_none ||
6517 DSAStack->getDefaultDSA() == DSA_private ||
6518 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6521 switch (
C->getClauseKind()) {
6522 case OMPC_num_threads:
6523 case OMPC_dist_schedule:
6530 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_target)
6534 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_parallel)
6540 case OMPC_grainsize:
6541 case OMPC_num_tasks:
6544 case OMPC_novariants:
6545 case OMPC_nocontext:
6552 case OMPC_num_teams:
6553 case OMPC_thread_limit:
6560 case OMPC_proc_bind:
6562 case OMPC_firstprivate:
6563 case OMPC_lastprivate:
6565 case OMPC_reduction:
6566 case OMPC_task_reduction:
6567 case OMPC_in_reduction:
6571 case OMPC_copyprivate:
6574 case OMPC_mergeable:
6591 case OMPC_defaultmap:
6594 case OMPC_use_device_ptr:
6595 case OMPC_use_device_addr:
6596 case OMPC_is_device_ptr:
6597 case OMPC_has_device_addr:
6598 case OMPC_nontemporal:
6601 case OMPC_inclusive:
6602 case OMPC_exclusive:
6603 case OMPC_uses_allocators:
6608 case OMPC_allocator:
6611 case OMPC_threadprivate:
6614 case OMPC_unified_address:
6615 case OMPC_unified_shared_memory:
6616 case OMPC_reverse_offload:
6617 case OMPC_dynamic_allocators:
6618 case OMPC_atomic_default_mem_order:
6619 case OMPC_device_type:
6626 llvm_unreachable(
"Unexpected clause");
6628 for (
Stmt *CC :
C->children()) {
6630 DSAChecker.Visit(CC);
6633 for (
const auto &
P : DSAChecker.getVarsWithInheritedDSA())
6634 VarsWithInheritedDSA[
P.getFirst()] =
P.getSecond();
6636 for (
const auto &
P : VarsWithInheritedDSA) {
6637 if (
P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(
P.getFirst()))
6640 if (
DSAStack->getDefaultDSA() == DSA_none ||
6641 DSAStack->getDefaultDSA() == DSA_private ||
6642 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6643 Diag(
P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6644 <<
P.first <<
P.second->getSourceRange();
6645 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6647 Diag(
P.second->getExprLoc(),
6648 diag::err_omp_defaultmap_no_attr_for_variable)
6649 <<
P.first <<
P.second->getSourceRange();
6651 diag::note_omp_defaultmap_attr_none);
6657 if (isAllowedClauseForDirective(
D, OMPC_if,
getLangOpts().OpenMP))
6658 AllowedNameModifiers.push_back(
D);
6660 if (!AllowedNameModifiers.empty())
6674 DSAStack->addTargetDirLocation(StartLoc);
6685 assert(Aligneds.size() == Alignments.size());
6686 assert(Linears.size() == LinModifiers.size());
6687 assert(Linears.size() == Steps.size());
6688 if (!DG || DG.
get().isNull())
6691 const int SimdId = 0;
6692 if (!DG.
get().isSingleDecl()) {
6693 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6697 Decl *ADecl = DG.
get().getSingleDecl();
6698 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6699 ADecl = FTD->getTemplatedDecl();
6701 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6703 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6719 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6720 const Expr *UniformedLinearThis =
nullptr;
6721 for (
const Expr *
E : Uniforms) {
6723 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6724 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6725 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6726 FD->getParamDecl(PVD->getFunctionScopeIndex())
6728 UniformedArgs.try_emplace(PVD->getCanonicalDecl(),
E);
6731 if (isa<CXXThisExpr>(
E)) {
6732 UniformedLinearThis =
E;
6736 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6746 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6747 const Expr *AlignedThis =
nullptr;
6748 for (
const Expr *
E : Aligneds) {
6750 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6751 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6753 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6754 FD->getParamDecl(PVD->getFunctionScopeIndex())
6758 if (AlignedArgs.count(CanonPVD) > 0) {
6760 << 1 << getOpenMPClauseName(OMPC_aligned)
6762 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6763 diag::note_omp_explicit_dsa)
6764 << getOpenMPClauseName(OMPC_aligned);
6767 AlignedArgs[CanonPVD] =
E;
6769 .getNonReferenceType()
6770 .getUnqualifiedType()
6771 .getCanonicalType();
6776 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6781 if (isa<CXXThisExpr>(
E)) {
6786 << getOpenMPClauseName(OMPC_aligned);
6792 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6799 for (
Expr *
E : Alignments) {
6803 NewAligns.push_back(Align.
get());
6814 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6815 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
6816 auto MI = LinModifiers.begin();
6817 for (
const Expr *
E : Linears) {
6821 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6822 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6824 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6825 FD->getParamDecl(PVD->getFunctionScopeIndex())
6829 if (LinearArgs.count(CanonPVD) > 0) {
6831 << getOpenMPClauseName(OMPC_linear)
6833 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6834 diag::note_omp_explicit_dsa)
6835 << getOpenMPClauseName(OMPC_linear);
6839 if (UniformedArgs.count(CanonPVD) > 0) {
6841 << getOpenMPClauseName(OMPC_linear)
6843 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6844 diag::note_omp_explicit_dsa)
6845 << getOpenMPClauseName(OMPC_uniform);
6848 LinearArgs[CanonPVD] =
E;
6854 PVD->getOriginalType(),
6859 if (isa<CXXThisExpr>(
E)) {
6860 if (UniformedLinearThis) {
6862 << getOpenMPClauseName(OMPC_linear)
6863 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6865 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
6866 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6870 UniformedLinearThis =
E;
6879 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6881 Expr *Step =
nullptr;
6882 Expr *NewStep =
nullptr;
6884 for (
Expr *
E : Steps) {
6886 if (Step ==
E || !
E) {
6887 NewSteps.push_back(
E ? NewStep :
nullptr);
6891 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6892 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6894 if (UniformedArgs.count(CanonPVD) == 0) {
6901 NewSteps.push_back(Step);
6920 NewSteps.push_back(NewStep);
6922 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6924 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
6925 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
6926 const_cast<Expr **
>(Linears.data()), Linears.size(),
6927 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
6928 NewSteps.data(), NewSteps.size(), SR);
6936 "Expected function type with prototype.");
6938 "Expected function with type with no prototype.");
6940 "Expected function with prototype.");
6948 Param->setScopeInfo(0, Params.size());
6949 Param->setImplicit();
6950 Params.push_back(Param);
6953 FD->setParams(Params);
6960 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
6961 FD = UTemplDecl->getTemplatedDecl();
6963 FD = cast<FunctionDecl>(
D);
6964 assert(FD &&
"Expected a function declaration!");
6970 for (OMPAssumeAttr *AA : OMPAssumeScoped)
6973 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
6977SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
6978 : TI(&TI), NameSuffix(TI.getMangledName()) {}
6983 if (!
D.getIdentifier())
6986 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
6989 bool IsTemplated = !TemplateParamLists.empty();
6991 !DVScope.TI->isExtensionActive(
6992 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7009 for (
auto *Candidate : Lookup) {
7010 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7012 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7013 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7014 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7015 UDecl = FTD->getTemplatedDecl();
7016 }
else if (!IsTemplated)
7017 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7031 FType, UDeclTy,
false,
7038 Bases.push_back(UDecl);
7041 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7042 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7044 if (Bases.empty() && UseImplicitBase) {
7048 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7049 Bases.push_back(BaseTemplD->getTemplatedDecl());
7051 Bases.push_back(cast<FunctionDecl>(BaseD));
7054 std::string MangledName;
7055 MangledName +=
D.getIdentifier()->getName();
7057 MangledName += DVScope.NameSuffix;
7072 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
7073 FD = UTemplDecl->getTemplatedDecl();
7075 FD = cast<FunctionDecl>(
D);
7082 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7083 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7089 BaseFD->addAttr(OMPDeclareVariantA);
7108 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7111 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7114 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7118 std::function<void(StringRef)> DiagUnknownTrait = [
this,
7119 CE](StringRef ISATrait) {
7133 while (CalleeFnDecl) {
7134 for (OMPDeclareVariantAttr *A :
7136 Expr *VariantRef = A->getVariantFuncRef();
7138 VariantMatchInfo VMI;
7141 if (!isVariantApplicableInContext(VMI, OMPCtx,
7145 VMIs.push_back(VMI);
7146 Exprs.push_back(VariantRef);
7154 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7157 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7158 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7174 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7175 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7177 Context, MemberCall->getImplicitObjectArgument(),
7179 MemberCall->getValueKind(), MemberCall->getObjectKind());
7182 RParenLoc, ExecConfig);
7184 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7185 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7187 CalleeFnType, NewCalleeFnDecl->
getType(),
7198 VMIs.erase(VMIs.begin() + BestIdx);
7199 Exprs.erase(Exprs.begin() + BestIdx);
7200 }
while (!VMIs.empty());
7207std::optional<std::pair<FunctionDecl *, Expr *>>
7211 unsigned NumAppendArgs,
7214 if (!DG || DG.
get().isNull())
7215 return std::nullopt;
7217 const int VariantId = 1;
7219 if (!DG.
get().isSingleDecl()) {
7220 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7222 return std::nullopt;
7224 Decl *ADecl = DG.
get().getSingleDecl();
7225 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7226 ADecl = FTD->getTemplatedDecl();
7229 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7233 return std::nullopt;
7236 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7239 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7242 if (HasMultiVersionAttributes(FD)) {
7243 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7245 return std::nullopt;
7250 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7255 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7257 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7262 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7263 return std::nullopt;
7266 auto ShouldDelayChecks = [](
Expr *&
E,
bool) {
7272 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7274 return std::make_pair(FD, VariantRef);
7277 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&
E,
7278 bool IsScore) ->
bool {
7284 Diag(
E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7292 diag::err_omp_declare_variant_user_condition_not_constant)
7298 return std::nullopt;
7301 if (NumAppendArgs) {
7304 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7306 return std::nullopt;
7315 TD = dyn_cast_or_null<TypeDecl>(ND);
7318 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7319 return std::nullopt;
7322 if (PTy->isVariadic()) {
7323 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7324 return std::nullopt;
7327 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7328 Params.insert(Params.end(), NumAppendArgs, InteropType);
7329 AdjustedFnType = Context.
getFunctionType(PTy->getReturnType(), Params,
7330 PTy->getExtProtoInfo());
7338 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7339 if (Method && !Method->isStatic()) {
7340 const Type *ClassType =
7354 return std::nullopt;
7356 VariantRef = ER.
get();
7364 false, Sema::AllowedExplicit::None,
7370 diag::err_omp_declare_variant_incompat_types)
7372 << ((Method && !Method->isStatic()) ? FnPtrType : FD->
getType())
7374 return std::nullopt;
7379 return std::nullopt;
7382 if (Method && !Method->isStatic()) {
7383 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7384 if (
auto *UO = dyn_cast<UnaryOperator>(
7386 VariantRefCast = UO->getSubExpr();
7395 return std::nullopt;
7403 return std::nullopt;
7405 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7409 return std::nullopt;
7414 diag::err_omp_declare_variant_same_base_function)
7416 return std::nullopt;
7425 diag::err_omp_declare_variant_incompat_types)
7426 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7428 return std::nullopt;
7433 else if (NewFD->getType()->isFunctionNoProtoType())
7439 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7441 diag::warn_omp_declare_variant_marked_as_declare_variant)
7444 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7445 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7446 return std::nullopt;
7449 enum DoesntSupport {
7458 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7459 if (CXXFD->isVirtual()) {
7462 return std::nullopt;
7465 if (isa<CXXConstructorDecl>(FD)) {
7468 return std::nullopt;
7471 if (isa<CXXDestructorDecl>(FD)) {
7474 return std::nullopt;
7478 if (FD->isDeleted()) {
7481 return std::nullopt;
7484 if (FD->isDefaulted()) {
7487 return std::nullopt;
7490 if (FD->isConstexpr()) {
7492 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7493 return std::nullopt;
7503 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7505 PDiag(diag::err_omp_declare_variant_diff)
7509 return std::nullopt;
7510 return std::make_pair(FD, cast<Expr>(DRE));
7526 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7527 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7529 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7530 VariantMatchInfo VMI;
7532 if (!llvm::is_contained(
7533 VMI.ConstructTraits,
7534 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7535 if (!AllAdjustArgs.empty())
7536 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7537 << getOpenMPClauseName(OMPC_adjust_args);
7538 if (!AppendArgs.empty())
7539 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7540 << getOpenMPClauseName(OMPC_append_args);
7550 for (
Expr *
E : AllAdjustArgs) {
7552 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E)) {
7553 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7555 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7559 if (!AdjustVars.insert(CanonPVD).second) {
7560 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7569 Diag(
E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7573 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7575 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7576 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7577 AdjustArgsNeedDevicePtr.size(),
7578 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7584 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7585 assert(CS &&
"Captured statement expected");
7594 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7623struct LoopIterationSpace final {
7626 bool IsStrictCompare =
false;
7628 Expr *PreCond =
nullptr;
7631 Expr *NumIterations =
nullptr;
7633 Expr *CounterVar =
nullptr;
7635 Expr *PrivateCounterVar =
nullptr;
7637 Expr *CounterInit =
nullptr;
7640 Expr *CounterStep =
nullptr;
7642 bool Subtract =
false;
7652 Expr *MinValue =
nullptr;
7656 Expr *MaxValue =
nullptr;
7658 bool IsNonRectangularLB =
false;
7660 bool IsNonRectangularUB =
false;
7663 unsigned LoopDependentIdx = 0;
7667 Expr *FinalCondition =
nullptr;
7673class OpenMPIterationSpaceChecker {
7677 bool SupportsNonRectangular;
7693 Expr *LCRef =
nullptr;
7699 Expr *Step =
nullptr;
7706 std::optional<bool> TestIsLessOp;
7708 bool TestIsStrictOp =
false;
7710 bool SubtractStep =
false;
7715 std::optional<unsigned> InitDependOnLC;
7718 std::optional<unsigned> CondDependOnLC;
7720 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
7721 bool IsInitializer);
7727 OpenMPIterationSpaceChecker(
Sema &SemaRef,
bool SupportsNonRectangular,
7729 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7730 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7733 bool checkAndSetInit(
Stmt *S,
bool EmitDiags =
true);
7736 bool checkAndSetCond(
Expr *S);
7739 bool checkAndSetInc(
Expr *S);
7741 ValueDecl *getLoopDecl()
const {
return LCDecl; }
7743 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
7745 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
7747 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
7749 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
7751 bool shouldSubtractStep()
const {
return SubtractStep; }
7753 bool isStrictTestOp()
const {
return TestIsStrictOp; }
7755 Expr *buildNumIterations(
7757 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7761 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7764 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7765 DSAStackTy &DSA)
const;
7768 Expr *buildPrivateCounterVar()
const;
7772 Expr *buildCounterStep()
const;
7776 buildOrderedLoopData(
Scope *S,
Expr *Counter,
7777 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7781 std::pair<Expr *, Expr *> buildMinMaxValues(
7782 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7784 Expr *buildFinalCondition(
Scope *S)
const;
7786 bool dependent()
const;
7788 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
7790 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
7792 unsigned getLoopDependentIdx()
const {
7793 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7799 bool checkAndSetIncRHS(
Expr *RHS);
7804 bool setUB(
Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
7807 bool setStep(
Expr *NewStep,
bool Subtract);
7810bool OpenMPIterationSpaceChecker::dependent()
const {
7812 assert(!LB && !UB && !Step);
7820bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
7822 Expr *NewLB,
bool EmitDiags) {
7824 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
7825 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7829 LCRef = NewLCRefExpr;
7830 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7832 if ((Ctor->isCopyOrMoveConstructor() ||
7833 Ctor->isConvertingConstructor(
false)) &&
7834 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
7838 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
7842bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
7846 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
7847 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7852 TestIsLessOp = LessOp;
7853 TestIsStrictOp = StrictOp;
7854 ConditionSrcRange = SR;
7856 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
7860bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
7862 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
7872 NewStep = Val.
get();
7885 std::optional<llvm::APSInt>
Result =
7896 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7897 if (UB && (IsConstZero ||
7898 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7899 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7901 diag::err_omp_loop_incr_not_compatible)
7903 SemaRef.
Diag(ConditionLoc,
7904 diag::note_omp_loop_cond_requires_compatible_incr)
7905 << *TestIsLessOp << ConditionSrcRange;
7908 if (*TestIsLessOp == Subtract) {
7912 Subtract = !Subtract;
7917 SubtractStep = Subtract;
7924class LoopCounterRefChecker final
7931 bool IsInitializer =
true;
7932 bool SupportsNonRectangular;
7933 unsigned BaseLoopId = 0;
7936 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7937 << (IsInitializer ? 0 : 1);
7940 const auto &&
Data = Stack.isLoopControlVariable(VD);
7946 llvm::raw_svector_ostream OS(Name);
7950 diag::err_omp_wrong_dependency_iterator_type)
7952 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
7955 if (
Data.first && !SupportsNonRectangular) {
7956 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_invariant_dependency);
7960 (DepDecl || (PrevDepDecl &&
7962 if (!DepDecl && PrevDepDecl)
7963 DepDecl = PrevDepDecl;
7965 llvm::raw_svector_ostream OS(Name);
7969 diag::err_omp_invariant_or_linear_dependency)
7975 BaseLoopId =
Data.first;
7983 if (isa<VarDecl>(VD))
7984 return checkDecl(
E, VD);
7990 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
7991 return checkDecl(
E, VD);
7995 bool VisitStmt(
const Stmt *S) {
7997 for (
const Stmt *Child : S->children())
7998 Res = (Child && Visit(Child)) || Res;
8001 explicit LoopCounterRefChecker(
Sema &SemaRef, DSAStackTy &Stack,
8002 const ValueDecl *CurLCDecl,
bool IsInitializer,
8004 bool SupportsNonRectangular =
true)
8005 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8006 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8007 SupportsNonRectangular(SupportsNonRectangular) {}
8008 unsigned getBaseLoopId()
const {
8009 assert(CurLCDecl &&
"Expected loop dependency.");
8013 assert(CurLCDecl &&
"Expected loop dependency.");
8019std::optional<unsigned>
8020OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8021 bool IsInitializer) {
8023 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8024 DepDecl, SupportsNonRectangular);
8025 if (LoopStmtChecker.Visit(S)) {
8026 DepDecl = LoopStmtChecker.getDepDecl();
8027 return LoopStmtChecker.getBaseLoopId();
8029 return std::nullopt;
8032bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8043 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8047 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8048 if (!ExprTemp->cleanupsHaveSideEffects())
8049 S = ExprTemp->getSubExpr();
8051 InitSrcRange = S->getSourceRange();
8052 if (
Expr *
E = dyn_cast<Expr>(S))
8054 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8055 if (BO->getOpcode() == BO_Assign) {
8057 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8058 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8060 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8062 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8064 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8065 if (ME->isArrow() &&
8066 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8067 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8071 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8072 if (DS->isSingleDecl()) {
8073 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8074 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8077 SemaRef.Diag(S->getBeginLoc(),
8078 diag::ext_omp_loop_not_canonical_init)
8079 << S->getSourceRange();
8080 return setLCDeclAndLB(
8083 Var->getType().getNonReferenceType(),
8085 Var->getInit(), EmitDiags);
8089 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8090 if (CE->getOperator() == OO_Equal) {
8091 Expr *LHS = CE->getArg(0);
8092 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8093 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8095 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8097 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8099 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8100 if (ME->isArrow() &&
8101 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8102 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8108 if (dependent() || SemaRef.CurContext->isDependentContext())
8111 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8112 << S->getSourceRange();
8123 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(
E))
8125 if ((Ctor->isCopyOrMoveConstructor() ||
8126 Ctor->isConvertingConstructor(
false)) &&
8127 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8129 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(
E)) {
8130 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8133 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(
E))
8134 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8139bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8146 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8148 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8149 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8155 auto &&CheckAndSetCond =
8160 if (getInitLCDecl(LHS) == LCDecl)
8161 return setUB(
const_cast<Expr *
>(RHS),
8163 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8164 if (getInitLCDecl(RHS) == LCDecl)
8165 return setUB(
const_cast<Expr *
>(LHS),
8167 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8168 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8169 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8173 return std::nullopt;
8175 std::optional<bool> Res;
8176 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8179 RBO->getOperatorLoc());
8180 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8181 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8182 BO->getSourceRange(), BO->getOperatorLoc());
8183 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8184 if (CE->getNumArgs() == 2) {
8185 Res = CheckAndSetCond(
8187 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8192 if (dependent() || SemaRef.CurContext->isDependentContext())
8194 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8195 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8199bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8206 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8207 if (BO->isAdditiveOp()) {
8208 bool IsAdd = BO->getOpcode() == BO_Add;
8209 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8210 return setStep(BO->getRHS(), !IsAdd);
8211 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8212 return setStep(BO->getLHS(),
false);
8214 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8215 bool IsAdd = CE->getOperator() == OO_Plus;
8216 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8217 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8218 return setStep(CE->getArg(1), !IsAdd);
8219 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8220 return setStep(CE->getArg(0),
false);
8223 if (dependent() || SemaRef.CurContext->isDependentContext())
8225 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8230bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8245 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8248 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8249 if (!ExprTemp->cleanupsHaveSideEffects())
8250 S = ExprTemp->getSubExpr();
8252 IncrementSrcRange = S->getSourceRange();
8253 S = S->IgnoreParens();
8254 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8255 if (UO->isIncrementDecrementOp() &&
8256 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8257 return setStep(SemaRef
8258 .ActOnIntegerConstant(UO->getBeginLoc(),
8259 (UO->isDecrementOp() ? -1 : 1))
8262 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8263 switch (BO->getOpcode()) {
8266 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8267 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8270 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8271 return checkAndSetIncRHS(BO->getRHS());
8276 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8277 switch (CE->getOperator()) {
8280 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8281 return setStep(SemaRef
8282 .ActOnIntegerConstant(
8284 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8290 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8291 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8294 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8295 return checkAndSetIncRHS(CE->getArg(1));
8301 if (dependent() || SemaRef.CurContext->isDependentContext())
8303 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8304 << S->getSourceRange() << LCDecl;
8310 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8311 StringRef Name =
".capture_expr.") {
8318 auto I = Captures.find(
Capture);
8319 if (I != Captures.end())
8332 bool TestIsStrictOp,
bool RoundToStep,
8333 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8334 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8337 llvm::APSInt LRes, SRes;
8338 bool IsLowerConst =
false, IsStepConst =
false;
8339 if (std::optional<llvm::APSInt> Res =
8342 IsLowerConst =
true;
8344 if (std::optional<llvm::APSInt> Res =
8349 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8350 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8351 (TestIsStrictOp && LRes.isStrictlyPositive()));
8352 bool NeedToReorganize =
false;
8354 if (!NoNeedToConvert && IsLowerConst &&
8355 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8356 NoNeedToConvert =
true;
8358 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8359 ? LRes.getBitWidth()
8360 : SRes.getBitWidth();
8361 LRes = LRes.extend(BW + 1);
8362 LRes.setIsSigned(
true);
8363 SRes = SRes.extend(BW + 1);
8364 SRes.setIsSigned(
true);
8366 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8367 LRes = LRes.trunc(BW);
8369 if (TestIsStrictOp) {
8370 unsigned BW = LRes.getBitWidth();
8371 LRes = LRes.extend(BW + 1);
8372 LRes.setIsSigned(
true);
8375 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8377 LRes = LRes.trunc(BW);
8379 NeedToReorganize = NoNeedToConvert;
8382 bool IsUpperConst =
false;
8383 if (std::optional<llvm::APSInt> Res =
8386 IsUpperConst =
true;
8388 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8389 (!RoundToStep || IsStepConst)) {
8390 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8391 : URes.getBitWidth();
8392 LRes = LRes.extend(BW + 1);
8393 LRes.setIsSigned(
true);
8394 URes = URes.extend(BW + 1);
8395 URes.setIsSigned(
true);
8397 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8398 NeedToReorganize = NoNeedToConvert;
8403 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8409 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8412 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8423 if (!Lower || !Upper || NewStep.
isInvalid())
8429 if (NeedToReorganize) {
8443 S, DefaultLoc, BO_Add, Diff.
get(),
8453 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8457 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8473 S, DefaultLoc, BO_Sub, Diff.
get(),
8493 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8501Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8503 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8512 if (InitDependOnLC) {
8513 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8514 if (!IS.MinValue || !IS.MaxValue)
8523 IS.CounterVar, MinValue.
get());
8528 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8543 IS.CounterVar, MaxValue.
get());
8548 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8557 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8559 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8560 if (!LBMin || !LBMax)
8564 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8568 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8572 if (*TestIsLessOp) {
8576 MinLessMax, LBMin, LBMax);
8579 LBVal = MinLB.
get();
8584 MinLessMax, LBMax, LBMin);
8587 LBVal = MaxLB.
get();
8591 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8594 LBVal = LBMinVal.
get();
8598 if (CondDependOnLC) {
8599 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8600 if (!IS.MinValue || !IS.MaxValue)
8609 IS.CounterVar, MinValue.
get());
8614 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8629 IS.CounterVar, MaxValue.
get());
8634 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
8643 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
8645 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
8646 if (!UBMin || !UBMax)
8650 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8653 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
8654 Captures,
".min_greater_max")
8658 if (*TestIsLessOp) {
8662 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8665 UBVal = MaxUB.
get();
8670 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8673 UBVal = MinUB.
get();
8676 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8677 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8678 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
8679 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
8680 if (!Upper || !Lower)
8683 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8684 Step, VarType, TestIsStrictOp,
8693 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
8696 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
8699 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
8708 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
8709 if (NewSize !=
C.getTypeSize(
Type)) {
8710 if (NewSize <
C.getTypeSize(
Type)) {
8711 assert(NewSize == 64 &&
"incorrect loop var size");
8712 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8713 << InitSrcRange << ConditionSrcRange;
8715 QualType NewType =
C.getIntTypeForBitwidth(
8717 C.getTypeSize(
Type) < NewSize);
8730std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8731 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8735 return std::make_pair(
nullptr,
nullptr);
8738 Expr *MinExpr =
nullptr;
8739 Expr *MaxExpr =
nullptr;
8740 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8741 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8743 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8745 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8747 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8749 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8750 if (!Upper || !Lower)
8751 return std::make_pair(
nullptr,
nullptr);
8761 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8762 Step, VarType, TestIsStrictOp,
8765 return std::make_pair(
nullptr,
nullptr);
8771 return std::make_pair(
nullptr,
nullptr);
8773 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8775 return std::make_pair(
nullptr,
nullptr);
8776 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
8778 return std::make_pair(
nullptr,
nullptr);
8783 return std::make_pair(
nullptr,
nullptr);
8795 return std::make_pair(
nullptr,
nullptr);
8797 if (*TestIsLessOp) {
8801 S, DefaultLoc, BO_Add,
8805 return std::make_pair(
nullptr,
nullptr);
8810 S, DefaultLoc, BO_Sub,
8814 return std::make_pair(
nullptr,
nullptr);
8823 return std::make_pair(
nullptr,
nullptr);
8828 return std::make_pair(
nullptr,
nullptr);
8831 MaxExpr = Diff.
get();
8833 MinExpr = Diff.
get();
8835 return std::make_pair(MinExpr, MaxExpr);
8838Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
8839 if (InitDependOnLC || CondDependOnLC)
8844Expr *OpenMPIterationSpaceChecker::buildPreCond(
8846 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8851 if (CondDependOnLC || InitDependOnLC)
8862 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8863 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8869 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8870 : (TestIsStrictOp ? BO_GT : BO_GE),
8871 NewLB.
get(), NewUB.
get());
8881 return CondExpr.
isUsable() ? CondExpr.
get() : Cond;
8885DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8886 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8887 DSAStackTy &DSA)
const {
8888 auto *VD = dyn_cast<VarDecl>(LCDecl);
8893 const DSAStackTy::DSAVarData
Data =
8894 DSA.getTopDSA(LCDecl,
false);
8898 Captures.insert(std::make_pair(LCRef, Ref));
8901 return cast<DeclRefExpr>(LCRef);
8904Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
8910 isa<VarDecl>(LCDecl)
8921Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
8924Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
8926Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
8934 assert((OOK == OO_Plus || OOK == OO_Minus) &&
8935 "Expected only + or - operations for depend clauses.");
8947 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
8949 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
8950 if (!Upper || !Lower)
8954 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
8955 false,
false, Captures);
8965 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
8966 assert(
Init &&
"Expected loop in canonical form.");
8967 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
8973 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
8975 if (!ISC.checkAndSetInit(
Init,
false)) {
8977 auto *VD = dyn_cast<VarDecl>(
D);
8985 VD = cast<VarDecl>(PrivateRef->
getDecl());
8988 DSAStack->addLoopControlVariable(
D, VD);
8991 DSAStack->resetPossibleLoopCounter();
8992 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9005 DSAStackTy::DSAVarData DVar =
9009 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9012 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9015 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9018 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9020 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9022 IsOpenMPTaskloopDirective(DKind) ||
9025 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9026 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9027 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9028 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9029 << getOpenMPClauseName(PredeterminedCKind);
9030 if (DVar.RefExpr ==
nullptr)
9031 DVar.CKind = PredeterminedCKind;
9033 }
else if (LoopDeclRefExpr) {
9038 if (DVar.CKind == OMPC_unknown)
9039 DSAStack->addDSA(
D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9043 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9048class OMPDoacrossKind {
9051 return C->getDependenceType() == OMPC_DOACROSS_source ||
9052 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9055 return C->getDependenceType() == OMPC_DOACROSS_sink;
9058 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9066 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9067 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9068 Expr *OrderedLoopCountExpr,
9071 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9076 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9077 S = CanonLoop->getLoopStmt();
9078 auto *For = dyn_cast_or_null<ForStmt>(S);
9079 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9081 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9082 SemaRef.
Diag(S->getBeginLoc(), diag::err_omp_not_for)
9083 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9084 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9085 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9086 if (TotalNestedLoopCount > 1) {
9087 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9088 SemaRef.
Diag(DSA.getConstructLoc(),
9089 diag::note_omp_collapse_ordered_expr)
9092 else if (CollapseLoopCountExpr)
9094 diag::note_omp_collapse_ordered_expr)
9098 diag::note_omp_collapse_ordered_expr)
9103 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9109 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9110 For ? For->getForLoc() : CXXFor->getForLoc());
9113 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9114 if (ISC.checkAndSetInit(
Init))
9117 bool HasErrors =
false;
9120 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9130 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9144 VarsWithImplicitDSA.erase(LCDecl);
9149 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9152 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9159 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9160 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9161 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9162 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9169 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9170 ISC.buildCounterVar(Captures, DSA);
9171 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9172 ISC.buildPrivateCounterVar();
9173 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9174 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9175 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9176 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9177 ISC.getConditionSrcRange();
9178 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9179 ISC.getIncrementSrcRange();
9180 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9181 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9182 ISC.isStrictTestOp();
9183 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9184 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9185 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9186 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9187 ISC.buildFinalCondition(DSA.getCurScope());
9188 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9189 ISC.doesInitDependOnLC();
9190 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9191 ISC.doesCondDependOnLC();
9192 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9193 ISC.getLoopDependentIdx();
9196 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9197 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9198 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9199 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9200 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9201 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9202 if (!HasErrors && DSA.isOrderedRegion()) {
9203 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9204 if (CurrentNestedLoopCount <
9205 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9206 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9207 CurrentNestedLoopCount,
9208 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9209 DSA.getOrderedRegionParam().second->setLoopCounter(
9210 CurrentNestedLoopCount,
9211 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9214 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9215 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9216 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9218 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9219 if (CurrentNestedLoopCount >= NumLoops) {
9223 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9224 Pair.second.size() <= CurrentNestedLoopCount) {
9226 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9229 OMPDoacrossKind ODK;
9230 if (DoacrossC && ODK.isSink(DoacrossC) &&
9231 Pair.second.size() <= CurrentNestedLoopCount) {
9233 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9238 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9239 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9240 (DoacrossC && ODK.isSource(DoacrossC)))
9241 CntValue = ISC.buildOrderedLoopData(
9243 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9245 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9248 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9256 CntValue = ISC.buildOrderedLoopData(
9258 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9259 DepLoc, Inc, clang::OO_Minus);
9261 CntValue = ISC.buildOrderedLoopData(
9263 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9264 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9265 Pair.second[CurrentNestedLoopCount].second);
9267 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9269 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9280 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9284 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9305 bool IsNonRectangularLB,
9306 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9315 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9330 if (Captures && !IsNonRectangularLB)
9331 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9340 Update.get()->getType()->isOverloadableType()) {
9347 SemaRef.
BuildBinOp(S,
Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9348 VarRef.
get(), SavedUpdate.
get());
9359 NewStart.
get(), SavedUpdate.
get());
9383 unsigned HasBits =
C.getTypeSize(OldType);
9384 if (HasBits >= Bits)
9387 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9397 if (std::optional<llvm::APSInt>
Result =
9406 if (!PreInits.empty()) {
9427 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9436 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9437 if (!Captures.empty()) {
9439 for (
const auto &Pair : Captures)
9440 PreInits.push_back(Pair.second->getDecl());
9448 if (PreInits.empty())
9452 for (
Stmt *S : PreInits)
9459 Expr *PostUpdate =
nullptr;
9460 if (!PostUpdates.empty()) {
9461 for (
Expr *
E : PostUpdates) {
9467 PostUpdate = PostUpdate
9482 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9486 unsigned NestedLoopCount = 1;
9487 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9490 if (CollapseLoopCountExpr) {
9495 NestedLoopCount =
Result.Val.getInt().getLimitedValue();
9501 unsigned OrderedLoopCount = 1;
9502 if (OrderedLoopCountExpr) {
9509 if (
Result.getLimitedValue() < NestedLoopCount) {
9511 diag::err_omp_wrong_ordered_loop_count)
9514 diag::note_collapse_loop_count)
9517 OrderedLoopCount =
Result.getLimitedValue();
9525 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9526 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9530 SupportsNonPerfectlyNested, NumLoops,
9531 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9532 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9533 &IterSpaces, &Captures](
unsigned Cnt,
Stmt *CurStmt) {
9535 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9536 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9537 VarsWithImplicitDSA, IterSpaces, Captures))
9539 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9540 IterSpaces[Cnt].CounterVar) {
9542 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9543 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9544 Captures[DRE] = DRE;
9550 Stmt *DependentPreInits = Transform->getPreInits();
9551 if (!DependentPreInits)
9558 for (
Stmt *S : Constituents) {
9559 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9560 for (
Decl *
C : DC->decls()) {
9561 auto *
D = cast<VarDecl>(
C);
9563 SemaRef,
D,
D->getType().getNonReferenceType(),
9565 Captures[Ref] = Ref;
9572 Built.
clear( NestedLoopCount);
9575 return NestedLoopCount;
9608 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
9609 Expr *N0 = IterSpaces[0].NumIterations;
9613 .PerformImplicitConversion(
9628 return NestedLoopCount;
9631 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
9633 Scope *CurScope = DSA.getCurScope();
9634 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9635 if (PreCond.isUsable()) {
9637 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9638 PreCond.get(), IterSpaces[Cnt].PreCond);
9640 Expr *N = IterSpaces[Cnt].NumIterations;
9642 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
9645 CurScope,
Loc, BO_Mul, LastIteration32.
get(),
9653 CurScope,
Loc, BO_Mul, LastIteration64.
get(),
9663 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
9665 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
9666 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9670 LastIteration64.
get(), SemaRef))))
9671 LastIteration = LastIteration32;
9690 LastIteration.
get(),
9702 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
9703 LastIteration = SaveRef;
9716 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9745 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
9754 UB.
get(), LastIteration.
get());
9757 LastIteration.
get(), UB.
get());
9758 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
9783 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
9786 LastIteration.
get(), CombUB.
get());
9787 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
9792 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9796 "Unexpected number of parameters in loop combined directive");
9837 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
9843 bool UseStrictCompare =
9845 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
9846 return LIS.IsStrictCompare;
9852 if (UseStrictCompare) {
9855 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9867 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
9870 NumIterations.
get());
9873 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
9874 NumIterations.
get());
9879 Expr *BoundCombUB = CombUB.
get();
9880 if (UseStrictCompare) {
9884 CurScope, CondLoc, BO_Add, BoundCombUB,
9892 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9893 IV.
get(), BoundCombUB);
9900 if (!Inc.isUsable())
9902 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
9904 if (!Inc.isUsable())
9911 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
9944 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
9956 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
9970 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
9973 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
9974 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
9978 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
9979 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
9983 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
9994 DistEUBLoc, NewPrevUB.
get());
9999 UB.
get(), NewPrevUB.
get());
10001 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10002 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10010 Expr *BoundPrevUB = PrevUB.
get();
10011 if (UseStrictCompare) {
10015 CurScope, CondLoc, BO_Add, BoundPrevUB,
10023 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10024 IV.
get(), BoundPrevUB);
10028 bool HasErrors =
false;
10029 Built.
Counters.resize(NestedLoopCount);
10030 Built.
Inits.resize(NestedLoopCount);
10031 Built.
Updates.resize(NestedLoopCount);
10032 Built.
Finals.resize(NestedLoopCount);
10053 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10054 LoopIterationSpace &IS = IterSpaces[Cnt];
10060 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10061 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10062 IterSpaces[K].NumIterations);
10067 if (Cnt + 1 < NestedLoopCount)
10072 if (!
Iter.isUsable()) {
10081 if (Cnt + 1 < NestedLoopCount)
10086 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10089 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10091 SemaRef, VD, IS.CounterVar->
getType(), IS.CounterVar->getExprLoc(),
10095 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10096 if (!
Init.isUsable()) {
10101 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
Iter,
10102 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10103 if (!
Update.isUsable()) {
10111 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10112 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10113 if (!Final.isUsable()) {
10118 if (!
Update.isUsable() || !Final.isUsable()) {
10123 Built.
Counters[Cnt] = IS.CounterVar;
10127 Built.
Finals[Cnt] = Final.get();
10131 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10150 Built.
PreCond = PreCond.get();
10154 Built.
Inc = Inc.get();
10155 Built.
LB = LB.
get();
10156 Built.
UB = UB.
get();
10157 Built.
IL = IL.
get();
10158 Built.
ST = ST.
get();
10160 Built.
NLB = NextLB.
get();
10161 Built.
NUB = NextUB.
get();
10176 return NestedLoopCount;
10180 auto CollapseClauses =
10181 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10182 if (CollapseClauses.begin() != CollapseClauses.end())
10183 return (*CollapseClauses.begin())->getNumForLoops();
10188 auto OrderedClauses =
10189 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10190 if (OrderedClauses.begin() != OrderedClauses.end())
10191 return (*OrderedClauses.begin())->getNumForLoops();
10200 for (
const OMPClause *Clause : Clauses) {
10202 Safelen = cast<OMPSafelenClause>(Clause);
10204 Simdlen = cast<OMPSimdlenClause>(Clause);
10205 if (Safelen && Simdlen)
10209 if (Simdlen && Safelen) {
10223 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10224 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10229 if (SimdlenRes > SafelenRes) {
10231 diag::err_omp_wrong_simdlen_safelen_values)
10247 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10254 if (NestedLoopCount == 0)
10264 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10265 return SimdDirective;
10274 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10281 if (NestedLoopCount == 0)
10288 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10290 return ForDirective;
10301 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10305 unsigned NestedLoopCount =
10308 VarsWithImplicitDSA, B);
10309 if (NestedLoopCount == 0)
10319 NestedLoopCount, Clauses, AStmt, B);
10323 Stmt *AStmt, DSAStackTy *Stack) {
10327 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10328 auto BaseStmt = AStmt;
10329 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10331 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10332 auto S =
C->children();
10333 if (S.begin() == S.end())
10337 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10338 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10340 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10341 diag::err_omp_sections_substmt_not_section)
10342 << getOpenMPDirectiveName(DKind);
10345 cast<OMPSectionDirective>(SectionStmt)
10346 ->setHasCancel(Stack->isCancelRegion());
10349 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10350 << getOpenMPDirectiveName(DKind);
10385 if (
auto *CE = dyn_cast<CallExpr>(
E))
10386 if (CE->getDirectCallee())
10398 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10408 Expr *TargetCall =
nullptr;
10410 auto *
E = dyn_cast<Expr>(S);
10412 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10418 if (
auto *BO = dyn_cast<BinaryOperator>(
E)) {
10419 if (BO->getOpcode() == BO_Assign)
10422 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(
E))
10423 if (COCE->getOperator() == OO_Equal)
10438 Clauses, AStmt, TargetCallLoc);
10443 DSAStackTy *Stack) {
10444 bool ErrorFound =
false;
10446 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10447 for (
Expr *RefExpr : LPC->varlists()) {
10450 Expr *SimpleRefExpr = RefExpr;
10453 auto &&Info = Stack->isLoopControlVariable(
D);
10455 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10456 << getOpenMPDirectiveName(K);
10485 if (NestedLoopCount == 0)
10489 "omp loop exprs were not built");
10492 NestedLoopCount, Clauses, AStmt, B);
10511 unsigned NestedLoopCount =
10514 VarsWithImplicitDSA, B);
10515 if (NestedLoopCount == 0)
10519 "omp loop exprs were not built");
10521 DSAStack->setParentTeamsRegionLoc(StartLoc);
10524 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10545 unsigned NestedLoopCount =
10548 VarsWithImplicitDSA, B);
10549 if (NestedLoopCount == 0)
10553 "omp loop exprs were not built");
10556 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10578 unsigned NestedLoopCount =
10581 VarsWithImplicitDSA, B);
10582 if (NestedLoopCount == 0)
10586 "omp loop exprs were not built");
10589 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10610 unsigned NestedLoopCount =
10613 VarsWithImplicitDSA, B);
10614 if (NestedLoopCount == 0)
10618 "omp loop exprs were not built");
10621 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10631 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10638 const OMPClause *Copyprivate =
nullptr;
10639 for (
const OMPClause *Clause : Clauses) {
10643 Copyprivate = Clause;
10644 if (Copyprivate && Nowait) {
10646 diag::err_omp_single_copyprivate_with_nowait);
10686 bool ErrorFound =
false;
10689 bool DependentHint =
false;
10691 if (
C->getClauseKind() == OMPC_hint) {
10693 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10696 Expr *
E = cast<OMPHintClause>(
C)->getHint();
10699 DependentHint =
true;
10702 HintLoc =
C->getBeginLoc();
10708 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
10709 if (Pair.first && DirName.
getName() && !DependentHint) {
10710 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10711 Diag(StartLoc, diag::err_omp_critical_with_hint);
10713 Diag(HintLoc, diag::note_omp_critical_hint_here)
10714 << 0 <<
toString(Hint, 10,
false);
10716 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10717 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
10718 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
10723 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10731 EndLoc, Clauses, AStmt);
10732 if (!Pair.first && DirName.
getName() && !DependentHint)
10733 DSAStack->addCriticalWithHint(Dir, Hint);
10748 unsigned NestedLoopCount =
10751 VarsWithImplicitDSA, B);
10752 if (NestedLoopCount == 0)
10759 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10775 unsigned NestedLoopCount =
10778 VarsWithImplicitDSA, B);
10779 if (NestedLoopCount == 0)
10789 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10802 DSAStack->getTaskgroupReductionRef());
10815 DSAStack->getTaskgroupReductionRef());
10836 bool ErrorFound =
false;
10838 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
10842 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10843 << getOpenMPClauseName(
C->getClauseKind())
10865 {OMPC_detach, OMPC_mergeable}))
10871 AStmt,
DSAStack->isCancelRegion());
10887 bool InExContext) {
10889 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
10891 if (AtC && !InExContext && AtC->
getAtKind() == OMPC_AT_execution) {
10897 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
10899 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
10902 if (!AtC || AtC->
getAtKind() == OMPC_AT_compilation) {
10903 if (SeverityC && SeverityC->
getSeverityKind() == OMPC_SEVERITY_warning)
10905 << (ME ? cast<StringLiteral>(ME)->getString() :
"WARNING");
10907 Diag(StartLoc, diag::err_diagnose_if_succeeded)
10908 << (ME ? cast<StringLiteral>(ME)->getString() :
"ERROR");
10909 if (!SeverityC || SeverityC->
getSeverityKind() != OMPC_SEVERITY_warning)
10920 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
10922 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
10924 if (NowaitC && !HasDependC) {
10925 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
10940 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10946 DSAStack->getTaskgroupReductionRef());
10955 if (
C->getClauseKind() == OMPC_flush)
10956 FC = cast<OMPFlushClause>(
C);
10963 if (
C->getClauseKind() == OMPC_acq_rel ||
10964 C->getClauseKind() == OMPC_acquire ||
10965 C->getClauseKind() == OMPC_release) {
10966 if (MemOrderKind != OMPC_unknown) {
10967 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
10968 << getOpenMPDirectiveName(OMPD_flush) << 1
10970 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
10971 << getOpenMPClauseName(MemOrderKind);
10973 MemOrderKind =
C->getClauseKind();
10974 MemOrderLoc =
C->getBeginLoc();
10978 if (FC && OrderClause) {
10981 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
10991 if (Clauses.empty()) {
10992 Diag(StartLoc, diag::err_omp_depobj_expected);
10994 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
10995 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
10999 if (Clauses.size() > 2) {
11000 Diag(Clauses[2]->getBeginLoc(),
11001 diag::err_omp_depobj_single_clause_expected);
11003 }
else if (Clauses.size() < 1) {
11004 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11014 if (Clauses.size() != 1) {
11015 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11016 diag::err_omp_scan_single_clause_expected);
11021 Scope *ParentS = S->getParent();
11024 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11025 << getOpenMPDirectiveName(OMPD_scan) << 5);
11029 if (
DSAStack->doesParentHasScanDirective()) {
11030 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11032 diag::note_omp_previous_directive)
11036 DSAStack->setParentHasScanDirective(StartLoc);
11044 const OMPClause *DependFound =
nullptr;
11045 const OMPClause *DependSourceClause =
nullptr;
11046 const OMPClause *DependSinkClause =
nullptr;
11047 const OMPClause *DoacrossFound =
nullptr;
11048 const OMPClause *DoacrossSourceClause =
nullptr;
11049 const OMPClause *DoacrossSinkClause =
nullptr;
11050 bool ErrorFound =
false;
11054 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11055 auto DC = dyn_cast<OMPDependClause>(
C);
11057 DependFound = DC ?
C :
nullptr;
11058 DoacrossFound = DOC ?
C :
nullptr;
11059 OMPDoacrossKind ODK;
11060 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11061 (DOC && (ODK.isSource(DOC)))) {
11062 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11063 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11064 << getOpenMPDirectiveName(OMPD_ordered)
11065 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11069 DependSourceClause =
C;
11071 DoacrossSourceClause =
C;
11073 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11074 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11075 << (DC ?
"depend" :
"doacross") << 0;
11078 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11079 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11080 if (DependSourceClause || DoacrossSourceClause) {
11081 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11082 << (DC ?
"depend" :
"doacross") << 1;
11086 DependSinkClause =
C;
11088 DoacrossSinkClause =
C;
11090 }
else if (
C->getClauseKind() == OMPC_threads) {
11091 TC = cast<OMPThreadsClause>(
C);
11092 }
else if (
C->getClauseKind() == OMPC_simd) {
11093 SC = cast<OMPSIMDClause>(
C);
11096 if (!ErrorFound && !SC &&
11101 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11104 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11107 Diag(
Loc, diag::err_omp_depend_clause_thread_simd)
11108 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11111 }
else if ((DependFound || DoacrossFound) &&
11112 !
DSAStack->getParentOrderedRegionParam().first) {
11115 Diag(
Loc, diag::err_omp_ordered_directive_without_param)
11116 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11118 }
else if (TC || Clauses.empty()) {
11119 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11121 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11122 << (TC !=
nullptr);
11127 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11135 if (!DependFound && !DoacrossFound) {
11136 if (
DSAStack->doesParentHasOrderedDirective()) {
11137 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11139 diag::note_omp_previous_directive)
11143 DSAStack->setParentHasOrderedDirective(StartLoc);
11147 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
11159class OpenMPAtomicUpdateChecker {
11161 enum ExprAnalysisErrorCode {
11165 NotABinaryOrUnaryExpression,
11167 NotAnUnaryIncDecExpression,
11173 NotABinaryExpression,
11176 NotABinaryOperator,
11179 NotAnUpdateExpression,
11182 NotAValidExpression,
11200 bool IsXLHSInRHSPart;
11205 bool IsPostfixUpdate;
11208 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11209 : SemaRef(SemaRef),
X(nullptr),
E(nullptr), UpdateExpr(nullptr),
11210 IsXLHSInRHSPart(
false), Op(BO_PtrMemD), IsPostfixUpdate(
false) {}
11218 bool checkStatement(
Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11220 Expr *getX()
const {
return X; }
11222 Expr *getExpr()
const {
return E; }
11226 Expr *getUpdateExpr()
const {
return UpdateExpr; }
11229 bool isXLHSInRHSPart()
const {
return IsXLHSInRHSPart; }
11233 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11236 bool checkBinaryOperation(
BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11237 unsigned NoteId = 0);
11240bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11241 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11242 ExprAnalysisErrorCode ErrorFound = NoError;
11248 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11250 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11252 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11253 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11254 AtomicInnerBinOp->isBitwiseOp()) {
11255 Op = AtomicInnerBinOp->getOpcode();
11256 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11257 Expr *LHS = AtomicInnerBinOp->getLHS();
11258 Expr *RHS = AtomicInnerBinOp->getRHS();
11259 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11266 if (XId == LHSId) {
11268 IsXLHSInRHSPart =
true;
11269 }
else if (XId == RHSId) {
11271 IsXLHSInRHSPart =
false;
11273 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11274 ErrorRange = AtomicInnerBinOp->getSourceRange();
11275 NoteLoc =
X->getExprLoc();
11276 NoteRange =
X->getSourceRange();
11277 ErrorFound = NotAnUpdateExpression;
11280 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11281 ErrorRange = AtomicInnerBinOp->getSourceRange();
11282 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11284 ErrorFound = NotABinaryOperator;
11289 ErrorFound = NotABinaryExpression;
11296 ErrorFound = NotAnAssignmentOp;
11298 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11299 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11300 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11304 E =
X = UpdateExpr =
nullptr;
11305 return ErrorFound != NoError;
11308bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11310 ExprAnalysisErrorCode ErrorFound = NoError;
11321 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11322 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11323 if (AtomicBody->getType()->isScalarType() ||
11324 AtomicBody->isInstantiationDependent()) {
11325 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11326 AtomicBody->IgnoreParenImpCasts())) {
11329 AtomicCompAssignOp->getOpcode());
11330 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11331 E = AtomicCompAssignOp->getRHS();
11332 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11333 IsXLHSInRHSPart =
true;
11334 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11335 AtomicBody->IgnoreParenImpCasts())) {
11337 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11339 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11340 AtomicBody->IgnoreParenImpCasts())) {
11342 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11343 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11344 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11345 OpLoc = AtomicUnaryOp->getOperatorLoc();
11346 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11348 IsXLHSInRHSPart =
true;
11350 ErrorFound = NotAnUnaryIncDecExpression;
11351 ErrorLoc = AtomicUnaryOp->getExprLoc();
11352 ErrorRange = AtomicUnaryOp->getSourceRange();
11353 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11356 }
else if (!AtomicBody->isInstantiationDependent()) {
11357 ErrorFound = NotABinaryOrUnaryExpression;
11358 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11359 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11360 }
else if (AtomicBody->containsErrors()) {
11361 ErrorFound = NotAValidExpression;
11362 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11363 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11366 ErrorFound = NotAScalarType;
11367 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11368 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11371 ErrorFound = NotAnExpression;
11372 NoteLoc = ErrorLoc = S->getBeginLoc();
11373 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11375 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11376 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11377 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11381 E =
X = UpdateExpr =
nullptr;
11382 if (ErrorFound == NoError &&
E &&
X) {
11392 IsXLHSInRHSPart ? OVEExpr : OVEX);
11399 UpdateExpr =
Update.get();
11401 return ErrorFound != NoError;
11405llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11406 llvm::FoldingSetNodeID
Id;
11407 S->IgnoreParenImpCasts()->Profile(
Id, Context,
true);
11412bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11414 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11417class OpenMPAtomicCompareChecker {
11464 struct ErrorInfoTy {
11472 OpenMPAtomicCompareChecker(
Sema &S) : ContextRef(S.getASTContext()) {}
11475 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11477 Expr *getX()
const {
return X; }
11478 Expr *getE()
const {
return E; }
11479 Expr *getD()
const {
return D; }
11480 Expr *getCond()
const {
return C; }
11481 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11500 bool IsXBinopExpr =
true;
11503 bool checkCondUpdateStmt(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11506 bool checkCondExprStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11509 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11511 static bool CheckValue(
const Expr *
E, ErrorInfoTy &ErrorInfo,
11512 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11516 if (ShouldBeLValue && !
E->
isLValue()) {
11517 ErrorInfo.Error = ErrorTy::XNotLValue;
11518 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11525 ErrorInfo.Error = ErrorTy::NotScalar;
11526 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11531 ErrorInfo.Error = ErrorTy::NotInteger;
11532 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11541bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11542 ErrorInfoTy &ErrorInfo) {
11543 auto *Then = S->getThen();
11544 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11545 if (CS->body_empty()) {
11546 ErrorInfo.Error = ErrorTy::NoStmt;
11547 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11548 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11551 if (CS->size() > 1) {
11552 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11553 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11554 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11557 Then = CS->body_front();
11560 auto *BO = dyn_cast<BinaryOperator>(Then);
11562 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11567 if (BO->getOpcode() != BO_Assign) {
11568 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11569 ErrorInfo.ErrorLoc = BO->getExprLoc();
11570 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11571 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11577 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11579 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11580 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11581 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11585 switch (Cond->getOpcode()) {
11589 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11590 E = Cond->getRHS();
11591 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11592 E = Cond->getLHS();
11594 ErrorInfo.Error = ErrorTy::InvalidComparison;
11595 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11596 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11604 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS()) &&
11605 checkIfTwoExprsAreSame(ContextRef,
E, Cond->getRHS())) {
11607 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, Cond->getLHS()) &&
11608 checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11610 IsXBinopExpr =
false;
11612 ErrorInfo.Error = ErrorTy::InvalidComparison;
11613 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11614 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11620 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11621 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11622 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11626 if (S->getElse()) {
11627 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11628 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11629 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11636bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
11637 ErrorInfoTy &ErrorInfo) {
11638 auto *BO = dyn_cast<BinaryOperator>(S);
11640 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11641 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11642 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11645 if (BO->getOpcode() != BO_Assign) {
11646 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11647 ErrorInfo.ErrorLoc = BO->getExprLoc();
11648 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11649 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11655 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11657 ErrorInfo.Error = ErrorTy::NotCondOp;
11658 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11659 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11663 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
11664 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11665 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11666 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11667 CO->getFalseExpr()->getSourceRange();
11671 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11673 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11674 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11675 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11676 CO->getCond()->getSourceRange();
11680 switch (Cond->getOpcode()) {
11683 D = CO->getTrueExpr();
11684 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11685 E = Cond->getRHS();
11686 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11687 E = Cond->getLHS();
11689 ErrorInfo.Error = ErrorTy::InvalidComparison;
11690 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11691 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11698 E = CO->getTrueExpr();
11699 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS()) &&
11700 checkIfTwoExprsAreSame(ContextRef,
E, Cond->getRHS())) {
11702 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, Cond->getLHS()) &&
11703 checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11705 IsXBinopExpr =
false;
11707 ErrorInfo.Error = ErrorTy::InvalidComparison;
11708 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11709 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11715 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11716 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11717 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11724bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
11726 assert(
X &&
E &&
"X and E cannot be nullptr");
11728 if (!CheckValue(
X, ErrorInfo,
true))
11731 if (!CheckValue(
E, ErrorInfo,
false))
11734 if (
D && !CheckValue(
D, ErrorInfo,
false))
11740bool OpenMPAtomicCompareChecker::checkStmt(
11741 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11742 auto *CS = dyn_cast<CompoundStmt>(S);
11744 if (CS->body_empty()) {
11745 ErrorInfo.Error = ErrorTy::NoStmt;
11746 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11747 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11751 if (CS->size() != 1) {
11752 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11753 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11754 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11757 S = CS->body_front();
11762 if (
auto *IS = dyn_cast<IfStmt>(S)) {
11768 Res = checkCondUpdateStmt(IS, ErrorInfo);
11774 Res = checkCondExprStmt(S, ErrorInfo);
11780 return checkType(ErrorInfo);
11783class OpenMPAtomicCompareCaptureChecker final
11784 :
public OpenMPAtomicCompareChecker {
11786 OpenMPAtomicCompareCaptureChecker(
Sema &S) : OpenMPAtomicCompareChecker(S) {}
11788 Expr *getV()
const {
return V; }
11789 Expr *getR()
const {
return R; }
11790 bool isFailOnly()
const {
return IsFailOnly; }
11791 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11794 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11797 bool checkType(ErrorInfoTy &ErrorInfo);
11809 bool checkForm3(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11813 bool checkForm45(
Stmt *S, ErrorInfoTy &ErrorInfo);
11820 bool IsFailOnly =
false;
11822 bool IsPostfixUpdate =
false;
11825bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11826 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11829 if (
V && !CheckValue(
V, ErrorInfo,
true))
11832 if (R && !CheckValue(R, ErrorInfo,
true,
true))
11838bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
11839 ErrorInfoTy &ErrorInfo) {
11842 auto *Then = S->getThen();
11843 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11844 if (CS->body_empty()) {
11845 ErrorInfo.Error = ErrorTy::NoStmt;
11846 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11847 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11850 if (CS->size() > 1) {
11851 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11852 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11853 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11856 Then = CS->body_front();
11859 auto *BO = dyn_cast<BinaryOperator>(Then);
11861 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11862 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11863 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11866 if (BO->getOpcode() != BO_Assign) {
11867 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11868 ErrorInfo.ErrorLoc = BO->getExprLoc();
11869 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11870 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11877 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11879 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11880 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11881 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11884 if (Cond->getOpcode() != BO_EQ) {
11885 ErrorInfo.Error = ErrorTy::NotEQ;
11886 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11887 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11891 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11892 E = Cond->getRHS();
11893 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11894 E = Cond->getLHS();
11896 ErrorInfo.Error = ErrorTy::InvalidComparison;
11897 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11898 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11904 if (!S->getElse()) {
11905 ErrorInfo.Error = ErrorTy::NoElse;
11906 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11907 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11911 auto *Else = S->getElse();
11912 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
11913 if (CS->body_empty()) {
11914 ErrorInfo.Error = ErrorTy::NoStmt;
11915 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11916 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11919 if (CS->size() > 1) {
11920 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11921 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11922 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11925 Else = CS->body_front();
11928 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
11930 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11931 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
11932 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
11935 if (ElseBO->getOpcode() != BO_Assign) {
11936 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11937 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
11938 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
11939 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
11943 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
11944 ErrorInfo.Error = ErrorTy::InvalidAssignment;
11945 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
11946 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11947 ElseBO->getRHS()->getSourceRange();
11951 V = ElseBO->getLHS();
11953 return checkType(ErrorInfo);
11956bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
11957 ErrorInfoTy &ErrorInfo) {
11960 auto *CS = cast<CompoundStmt>(S);
11961 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
11962 auto *S1 = cast<BinaryOperator>(CS->body_front());
11963 auto *S2 = cast<IfStmt>(CS->body_back());
11964 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
11966 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
11967 ErrorInfo.Error = ErrorTy::InvalidCondition;
11968 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
11969 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
11975 auto *Then = S2->getThen();
11976 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
11977 if (ThenCS->body_empty()) {
11978 ErrorInfo.Error = ErrorTy::NoStmt;
11979 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
11980 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
11983 if (ThenCS->size() > 1) {
11984 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11985 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
11986 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
11989 Then = ThenCS->body_front();
11992 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
11994 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11995 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
11996 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
11999 if (ThenBO->getOpcode() != BO_Assign) {
12000 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12001 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12002 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12003 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12007 X = ThenBO->getLHS();
12008 D = ThenBO->getRHS();
12010 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12011 if (BO->getOpcode() != BO_EQ) {
12012 ErrorInfo.Error = ErrorTy::NotEQ;
12013 ErrorInfo.ErrorLoc = BO->getExprLoc();
12014 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12015 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12021 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12023 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12026 ErrorInfo.Error = ErrorTy::InvalidComparison;
12027 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->
getExprLoc();
12028 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12032 if (S2->getElse()) {
12035 auto *Else = S2->getElse();
12036 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12037 if (ElseCS->body_empty()) {
12038 ErrorInfo.Error = ErrorTy::NoStmt;
12039 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12040 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12043 if (ElseCS->size() > 1) {
12044 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12045 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12046 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12049 Else = ElseCS->body_front();
12052 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12054 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12055 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12056 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12059 if (ElseBO->getOpcode() != BO_Assign) {
12060 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12061 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12062 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12066 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12067 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12068 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12069 ErrorInfo.NoteLoc =
X->getExprLoc();
12070 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12071 ErrorInfo.NoteRange =
X->getSourceRange();
12075 V = ElseBO->getLHS();
12078 return checkType(ErrorInfo);
12081bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12082 ErrorInfoTy &ErrorInfo) {
12084 if (
auto *IS = dyn_cast<IfStmt>(S))
12085 return checkForm3(IS, ErrorInfo);
12087 auto *CS = dyn_cast<CompoundStmt>(S);
12089 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12090 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12094 if (CS->body_empty()) {
12095 ErrorInfo.Error = ErrorTy::NoStmt;
12096 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12097 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12102 if (CS->size() == 1) {
12103 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12105 ErrorInfo.Error = ErrorTy::NotIfStmt;
12106 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12107 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12112 return checkForm3(IS, ErrorInfo);
12113 }
else if (CS->size() == 2) {
12114 auto *S1 = CS->body_front();
12115 auto *S2 = CS->body_back();
12117 Stmt *UpdateStmt =
nullptr;
12118 Stmt *CondUpdateStmt =
nullptr;
12119 Stmt *CondExprStmt =
nullptr;
12121 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12127 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12128 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12130 if (isa<IfStmt>(S2))
12131 return checkForm45(CS, ErrorInfo);
12136 IsPostfixUpdate =
true;
12138 if (isa<IfStmt>(S2)) {
12140 CondUpdateStmt = S2;
12149 CondUpdateStmt = S1;
12152 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12153 auto *IS = dyn_cast<IfStmt>(CUS);
12155 ErrorInfo.Error = ErrorTy::NotIfStmt;
12156 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12157 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12161 return checkCondUpdateStmt(IS, ErrorInfo);
12165 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12166 auto *BO = dyn_cast<BinaryOperator>(US);
12168 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12169 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12170 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12173 if (BO->getOpcode() != BO_Assign) {
12174 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12175 ErrorInfo.ErrorLoc = BO->getExprLoc();
12176 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12177 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12180 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12181 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12182 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12184 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12189 this->
V = BO->getLHS();
12194 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12196 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12198 if (!CheckUpdateStmt(UpdateStmt))
12201 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12202 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12203 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12207 return checkType(ErrorInfo);
12217 DSAStack->addAtomicDirectiveLoc(StartLoc);
12230 bool MutexClauseEncountered =
false;
12231 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12233 switch (
C->getClauseKind()) {
12237 MutexClauseEncountered =
true;
12240 case OMPC_compare: {
12241 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12242 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12244 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12245 << getOpenMPClauseName(AtomicKind);
12247 AtomicKind =
C->getClauseKind();
12248 AtomicKindLoc =
C->getBeginLoc();
12249 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12250 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12252 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12253 << getOpenMPClauseName(AtomicKind);
12260 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12261 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12262 << getOpenMPClauseName(
C->getClauseKind())
12272 case OMPC_relaxed: {
12273 if (MemOrderKind != OMPC_unknown) {
12274 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12275 << getOpenMPDirectiveName(OMPD_atomic) << 0
12277 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12278 << getOpenMPClauseName(MemOrderKind);
12280 MemOrderKind =
C->getClauseKind();
12281 MemOrderLoc =
C->getBeginLoc();
12289 llvm_unreachable(
"unknown clause is encountered");
12292 bool IsCompareCapture =
false;
12293 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12294 EncounteredAtomicKinds.contains(OMPC_capture)) {
12295 IsCompareCapture =
true;
12296 AtomicKind = OMPC_compare;
12305 if ((AtomicKind == OMPC_read &&
12306 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12307 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12308 AtomicKind == OMPC_unknown) &&
12309 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12311 if (AtomicKind == OMPC_unknown)
12313 Diag(
Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12314 << getOpenMPClauseName(AtomicKind)
12315 << (AtomicKind == OMPC_unknown ? 1 : 0)
12316 << getOpenMPClauseName(MemOrderKind);
12317 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12318 << getOpenMPClauseName(MemOrderKind);
12321 Stmt *Body = AStmt;
12322 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12323 Body = EWC->getSubExpr();
12328 Expr *UE =
nullptr;
12330 Expr *CE =
nullptr;
12332 bool IsXLHSInRHSPart =
false;
12333 bool IsPostfixUpdate =
false;
12334 bool IsFailOnly =
false;
12357 if (AtomicKind == OMPC_read) {
12364 } ErrorFound = NoError;
12369 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12370 const auto *AtomicBinOp =
12371 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12372 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12375 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12376 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12377 if (!
X->isLValue() || !
V->isLValue()) {
12378 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12379 ErrorFound = NotAnLValue;
12385 }
else if (!
X->isInstantiationDependent() ||
12386 !
V->isInstantiationDependent()) {
12387 const Expr *NotScalarExpr =
12388 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12391 ErrorFound = NotAScalarType;
12397 }
else if (!AtomicBody->isInstantiationDependent()) {
12398 ErrorFound = NotAnAssignmentOp;
12399 ErrorLoc = AtomicBody->getExprLoc();
12400 ErrorRange = AtomicBody->getSourceRange();
12402 : AtomicBody->getExprLoc();
12404 : AtomicBody->getSourceRange();
12407 ErrorFound = NotAnExpression;
12409 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12411 if (ErrorFound != NoError) {
12412 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12414 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12415 << ErrorFound << NoteRange;
12420 }
else if (AtomicKind == OMPC_write) {
12427 } ErrorFound = NoError;
12432 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12433 const auto *AtomicBinOp =
12434 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12435 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12438 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12440 if (!
X->isLValue()) {
12441 ErrorFound = NotAnLValue;
12444 NoteLoc =
X->getExprLoc();
12445 NoteRange =
X->getSourceRange();
12447 }
else if (!
X->isInstantiationDependent() ||
12449 const Expr *NotScalarExpr =
12450 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12453 ErrorFound = NotAScalarType;
12459 }
else if (!AtomicBody->isInstantiationDependent()) {
12460 ErrorFound = NotAnAssignmentOp;
12461 ErrorLoc = AtomicBody->getExprLoc();
12462 ErrorRange = AtomicBody->getSourceRange();
12464 : AtomicBody->getExprLoc();
12466 : AtomicBody->getSourceRange();
12469 ErrorFound = NotAnExpression;
12471 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12473 if (ErrorFound != NoError) {
12474 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12476 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12477 << ErrorFound << NoteRange;
12482 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12491 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12492 if (Checker.checkStatement(
12494 (AtomicKind == OMPC_update)
12495 ? diag::err_omp_atomic_update_not_expression_statement
12496 : diag::err_omp_atomic_not_expression_statement,
12497 diag::note_omp_atomic_update))
12500 E = Checker.getExpr();
12501 X = Checker.getX();
12502 UE = Checker.getUpdateExpr();
12503 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12505 }
else if (AtomicKind == OMPC_capture) {
12508 NotACompoundStatement,
12509 NotTwoSubstatements,
12510 NotASpecificExpression,
12512 } ErrorFound = NoError;
12515 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12524 const auto *AtomicBinOp =
12525 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12526 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12529 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12530 if (Checker.checkStatement(
12531 Body, diag::err_omp_atomic_capture_not_expression_statement,
12532 diag::note_omp_atomic_update))
12534 E = Checker.getExpr();
12535 X = Checker.getX();
12536 UE = Checker.getUpdateExpr();
12537 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12538 IsPostfixUpdate = Checker.isPostfixUpdate();
12539 }
else if (!AtomicBody->isInstantiationDependent()) {
12540 ErrorLoc = AtomicBody->getExprLoc();
12541 ErrorRange = AtomicBody->getSourceRange();
12543 : AtomicBody->getExprLoc();
12545 : AtomicBody->getSourceRange();
12546 ErrorFound = NotAnAssignmentOp;
12548 if (ErrorFound != NoError) {
12549 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12551 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12555 UE =
V =
E =
X =
nullptr;
12573 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
12575 if (CS->size() == 2) {
12577 Stmt *Second = CS->body_back();
12578 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
12579 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12580 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12581 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12583 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12584 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12586 if (IsUpdateExprFound) {
12587 BinOp = dyn_cast<BinaryOperator>(
First);
12588 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12600 llvm::FoldingSetNodeID XId, PossibleXId;
12601 Checker.getX()->
Profile(XId, Context,
true);
12602 PossibleX->
Profile(PossibleXId, Context,
true);
12603 IsUpdateExprFound = XId == PossibleXId;
12604 if (IsUpdateExprFound) {
12606 X = Checker.getX();
12607 E = Checker.getExpr();
12608 UE = Checker.getUpdateExpr();
12609 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12610 IsPostfixUpdate =
true;
12613 if (!IsUpdateExprFound) {
12614 IsUpdateExprFound = !Checker.checkStatement(
First);
12616 if (IsUpdateExprFound) {
12617 BinOp = dyn_cast<BinaryOperator>(Second);
12618 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12620 if (IsUpdateExprFound &&
12631 llvm::FoldingSetNodeID XId, PossibleXId;
12632 Checker.getX()->
Profile(XId, Context,
true);
12633 PossibleX->
Profile(PossibleXId, Context,
true);
12634 IsUpdateExprFound = XId == PossibleXId;
12635 if (IsUpdateExprFound) {
12637 X = Checker.getX();
12638 E = Checker.getExpr();
12639 UE = Checker.getUpdateExpr();
12640 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12641 IsPostfixUpdate =
false;
12645 if (!IsUpdateExprFound) {
12647 auto *FirstExpr = dyn_cast<Expr>(
First);
12648 auto *SecondExpr = dyn_cast<Expr>(Second);
12649 if (!FirstExpr || !SecondExpr ||
12650 !(FirstExpr->isInstantiationDependent() ||
12651 SecondExpr->isInstantiationDependent())) {
12652 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
12653 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12654 ErrorFound = NotAnAssignmentOp;
12655 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12656 :
First->getBeginLoc();
12657 NoteRange = ErrorRange = FirstBinOp
12658 ? FirstBinOp->getSourceRange()
12661 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12662 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12663 ErrorFound = NotAnAssignmentOp;
12664 NoteLoc = ErrorLoc = SecondBinOp
12665 ? SecondBinOp->getOperatorLoc()
12667 NoteRange = ErrorRange =
12668 SecondBinOp ? SecondBinOp->getSourceRange()
12671 Expr *PossibleXRHSInFirst =
12673 Expr *PossibleXLHSInSecond =
12675 llvm::FoldingSetNodeID X1Id, X2Id;
12676 PossibleXRHSInFirst->
Profile(X1Id, Context,
12678 PossibleXLHSInSecond->
Profile(X2Id, Context,
12680 IsUpdateExprFound = X1Id == X2Id;
12681 if (IsUpdateExprFound) {
12682 V = FirstBinOp->getLHS();
12683 X = SecondBinOp->getLHS();
12684 E = SecondBinOp->getRHS();
12686 IsXLHSInRHSPart =
false;
12687 IsPostfixUpdate =
true;
12689 ErrorFound = NotASpecificExpression;
12690 ErrorLoc = FirstBinOp->getExprLoc();
12691 ErrorRange = FirstBinOp->getSourceRange();
12692 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12693 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12701 NoteRange = ErrorRange =
12703 ErrorFound = NotTwoSubstatements;
12707 NoteRange = ErrorRange =
12709 ErrorFound = NotACompoundStatement;
12712 if (ErrorFound != NoError) {
12713 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12715 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12719 UE =
V =
E =
X =
nullptr;
12720 }
else if (AtomicKind == OMPC_compare) {
12721 if (IsCompareCapture) {
12722 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12723 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
12724 if (!Checker.checkStmt(Body, ErrorInfo)) {
12725 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12726 << ErrorInfo.ErrorRange;
12727 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12728 << ErrorInfo.Error << ErrorInfo.NoteRange;
12731 X = Checker.getX();
12732 E = Checker.getE();
12733 D = Checker.getD();
12734 CE = Checker.getCond();
12735 V = Checker.getV();
12736 R = Checker.getR();
12738 IsXLHSInRHSPart = Checker.isXBinopExpr();
12739 IsFailOnly = Checker.isFailOnly();
12740 IsPostfixUpdate = Checker.isPostfixUpdate();
12742 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12743 OpenMPAtomicCompareChecker Checker(
SemaRef);
12744 if (!Checker.checkStmt(Body, ErrorInfo)) {
12745 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12746 << ErrorInfo.ErrorRange;
12747 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12748 << ErrorInfo.Error << ErrorInfo.NoteRange;
12751 X = Checker.getX();
12752 E = Checker.getE();
12753 D = Checker.getD();
12754 CE = Checker.getCond();
12760 auto *It = find_if(Clauses, [](
OMPClause *
C) {
12761 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12763 if (It != Clauses.end()) {
12764 auto *Cond = dyn_cast<BinaryOperator>(CE);
12765 if (Cond->getOpcode() != BO_EQ) {
12766 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12768 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12769 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
12771 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12772 << ErrorInfo.ErrorRange;
12777 IsXLHSInRHSPart = Checker.isXBinopExpr();
12784 Context, StartLoc, EndLoc, Clauses, AStmt,
12785 {
X,
V, R,
E, UE,
D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12801 if (
DSAStack->hasInnerTeamsRegion()) {
12803 bool OMPTeamsFound =
true;
12804 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
12805 auto I = CS->body_begin();
12806 while (I != CS->body_end()) {
12807 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12809 if (!IsTeams || I != CS->body_begin()) {
12810 OMPTeamsFound =
false;
12811 if (IsTeams && I != CS->body_begin()) {
12820 assert(I != CS->body_end() &&
"Not found statement");
12823 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12826 if (!OMPTeamsFound) {
12827 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12829 diag::note_omp_nested_teams_construct_here);
12830 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12831 << isa<OMPExecutableDirective>(S);
12865 unsigned NestedLoopCount =
12868 VarsWithImplicitDSA, B);
12869 if (NestedLoopCount == 0)
12876 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12883 return llvm::any_of(
12884 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
12887template <
typename... Params>
12889 const Params... ClauseTypes) {
12896 if (
auto *TC = dyn_cast<OMPToClause>(
C))
12897 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
12898 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12899 (VD->isExternallyVisible() &&
12900 VD->getVisibility() != HiddenVisibility);
12902 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
12903 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
12904 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12905 (VD->isExternallyVisible() &&
12906 VD->getVisibility() != HiddenVisibility);
12920 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
12925 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
12927 !
hasClauses(Clauses, OMPC_use_device_addr))) {
12930 Expected =
"'map' or 'use_device_ptr'";
12932 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
12933 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12934 <<
Expected << getOpenMPDirectiveName(OMPD_target_data);
12955 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12956 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
12975 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12976 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
12992 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
12993 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
12998 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13015 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13019 DSAStack->setParentTeamsRegionLoc(StartLoc);
13028 if (
DSAStack->isParentNowaitRegion()) {
13029 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13032 if (
DSAStack->isParentOrderedRegion()) {
13033 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13037 EndLoc, CancelRegion);
13043 if (
DSAStack->isParentNowaitRegion()) {
13044 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13047 if (
DSAStack->isParentOrderedRegion()) {
13048 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13051 DSAStack->setParentCancelRegion(
true);
13058 const OMPClause *ReductionClause =
nullptr;
13059 const OMPClause *NogroupClause =
nullptr;
13061 if (
C->getClauseKind() == OMPC_reduction) {
13062 ReductionClause =
C;
13067 if (
C->getClauseKind() == OMPC_nogroup) {
13069 if (ReductionClause)
13074 if (ReductionClause && NogroupClause) {
13075 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13089 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13093 unsigned NestedLoopCount =
13096 *
DSAStack, VarsWithImplicitDSA, B);
13097 if (NestedLoopCount == 0)
13101 "omp for loop exprs were not built");
13107 {OMPC_grainsize, OMPC_num_tasks}))
13117 NestedLoopCount, Clauses, AStmt, B,
13130 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13134 unsigned NestedLoopCount =
13137 VarsWithImplicitDSA, B);
13138 if (NestedLoopCount == 0)
13148 {OMPC_grainsize, OMPC_num_tasks}))
13159 NestedLoopCount, Clauses, AStmt, B);
13168 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13172 unsigned NestedLoopCount =
13175 *
DSAStack, VarsWithImplicitDSA, B);
13176 if (NestedLoopCount == 0)
13180 "omp for loop exprs were not built");
13186 {OMPC_grainsize, OMPC_num_tasks}))
13196 NestedLoopCount, Clauses, AStmt, B,
13206 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13210 unsigned NestedLoopCount =
13213 *
DSAStack, VarsWithImplicitDSA, B);
13214 if (NestedLoopCount == 0)
13218 "omp for loop exprs were not built");
13224 {OMPC_grainsize, OMPC_num_tasks}))
13234 NestedLoopCount, Clauses, AStmt, B,
13247 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13251 unsigned NestedLoopCount =
13254 VarsWithImplicitDSA, B);
13255 if (NestedLoopCount == 0)
13265 {OMPC_grainsize, OMPC_num_tasks}))
13276 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13288 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13292 unsigned NestedLoopCount =
13295 VarsWithImplicitDSA, B);
13296 if (NestedLoopCount == 0)
13306 {OMPC_grainsize, OMPC_num_tasks}))
13317 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13335 VarsWithImplicitDSA, B);
13336 if (NestedLoopCount == 0)
13340 "omp for loop exprs were not built");
13346 {OMPC_grainsize, OMPC_num_tasks}))
13355 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13374 VarsWithImplicitDSA, B);
13375 if (NestedLoopCount == 0)
13379 "omp for loop exprs were not built");
13385 {OMPC_grainsize, OMPC_num_tasks}))
13394 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13405 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13413 VarsWithImplicitDSA, B);
13414 if (NestedLoopCount == 0)
13424 {OMPC_grainsize, OMPC_num_tasks}))
13435 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13445 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13453 VarsWithImplicitDSA, B);
13454 if (NestedLoopCount == 0)
13464 {OMPC_grainsize, OMPC_num_tasks}))
13475 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13484 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13488 unsigned NestedLoopCount =
13492 if (NestedLoopCount == 0)
13496 "omp for loop exprs were not built");
13500 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13501 return DistributeDirective;
13519 VarsWithImplicitDSA, B);
13520 if (NestedLoopCount == 0)
13524 "omp for loop exprs were not built");
13527 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13538 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13546 VarsWithImplicitDSA, B);
13547 if (NestedLoopCount == 0)
13557 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13572 unsigned NestedLoopCount =
13576 if (NestedLoopCount == 0)
13586 NestedLoopCount, Clauses, AStmt, B);
13604 VarsWithImplicitDSA, B);
13605 if (NestedLoopCount == 0)
13615 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13629 unsigned NestedLoopCount =
13632 VarsWithImplicitDSA, B);
13633 if (NestedLoopCount == 0)
13643 NestedLoopCount, Clauses, AStmt, B);
13658 unsigned NestedLoopCount =
13662 if (NestedLoopCount == 0)
13666 "omp teams distribute loop exprs were not built");
13668 DSAStack->setParentTeamsRegionLoc(StartLoc);
13671 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13689 VarsWithImplicitDSA, B);
13690 if (NestedLoopCount == 0)
13699 DSAStack->setParentTeamsRegionLoc(StartLoc);
13702 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13712 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13720 VarsWithImplicitDSA, B);
13721 if (NestedLoopCount == 0)
13730 DSAStack->setParentTeamsRegionLoc(StartLoc);
13733 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13743 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13751 VarsWithImplicitDSA, B);
13753 if (NestedLoopCount == 0)
13757 "omp for loop exprs were not built");
13759 DSAStack->setParentTeamsRegionLoc(StartLoc);
13762 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13775 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
13777 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
13779 return C->getClauseKind() == OMPC_ompx_bare;
13782 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13806 VarsWithImplicitDSA, B);
13807 if (NestedLoopCount == 0)
13811 "omp target teams distribute loop exprs were not built");
13814 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13824 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
13832 VarsWithImplicitDSA, B);
13833 if (NestedLoopCount == 0)
13840 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13851 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
13856 unsigned NestedLoopCount =
13861 if (NestedLoopCount == 0)
13871 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13881 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
13889 VarsWithImplicitDSA, B);
13890 if (NestedLoopCount == 0)
13900 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13903bool SemaOpenMP::checkTransformableLoopNest(
13907 OriginalInits.emplace_back();
13910 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
13912 VarsWithInheritedDSAType TmpDSA;
13913 unsigned SingleNumLoops =
13914 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
13915 TmpDSA, LoopHelpers[Cnt]);
13916 if (SingleNumLoops == 0)
13918 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
13919 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
13920 OriginalInits.back().push_back(For->getInit());
13921 Body = For->getBody();
13923 assert(isa<CXXForRangeStmt>(CurStmt) &&
13924 "Expected canonical for or range-based for loops.");
13925 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
13926 OriginalInits.back().push_back(CXXFor->getBeginStmt());
13927 Body = CXXFor->getBody();
13929 OriginalInits.emplace_back();
13933 Stmt *DependentPreInits;
13934 if (
auto *Dir = dyn_cast<OMPTileDirective>(Transform))
13935 DependentPreInits = Dir->getPreInits();
13936 else if (
auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
13937 DependentPreInits = Dir->getPreInits();
13938 else if (
auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
13939 DependentPreInits = Dir->getPreInits();
13940 else if (
auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
13941 DependentPreInits = Dir->getPreInits();
13943 llvm_unreachable(
"Unhandled loop transformation");
13947 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
13948 OriginalInits.pop_back();
13960 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
13961 Stmt *RangeInit = CXXRangeFor->getInit();
13963 PreInits.push_back(RangeInit);
13965 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
13970 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
13976 llvm::append_range(PreInits, OriginalInit);
13979 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.
PreInits)) {
13980 PreInits.push_back(
new (Context)
DeclStmt(
13981 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
13986 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
13987 if (isa<OMPCapturedExprDecl>(CounterDecl))
13988 PreInits.push_back(
new (Context)
DeclStmt(
13996 size_t NumLoops = LoopStmts.size();
13998 AStmt,
false, NumLoops,
13999 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14000 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14001 LoopStmts[Cnt] = CurStmt;
14004 assert(!is_contained(LoopStmts,
nullptr) &&
14005 "Expecting a loop statement for each affected loop");
14015 const auto *SizesClause =
14016 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14017 if (!SizesClause ||
14018 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *
E) { return !E; }))
14020 unsigned NumLoops = SizesClause->getNumSizes();
14028 Stmt *Body =
nullptr;
14030 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14037 NumLoops, AStmt,
nullptr,
nullptr);
14039 assert(LoopHelpers.size() == NumLoops &&
14040 "Expecting loop iteration space dimensionality to match number of "
14042 assert(OriginalInits.size() == NumLoops &&
14043 "Expecting loop iteration space dimensionality to match number of "
14051 CaptureVars CopyTransformer(
SemaRef);
14056 FloorIndVars.resize(NumLoops);
14057 TileIndVars.resize(NumLoops);
14058 for (
unsigned I = 0; I < NumLoops; ++I) {
14061 assert(LoopHelper.
Counters.size() == 1 &&
14062 "Expect single-dimensional loop iteration space");
14063 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14064 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14070 std::string FloorCntName =
14071 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14074 FloorIndVars[I] = FloorCntDecl;
14079 std::string TileCntName =
14080 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14085 auto *TileCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
14086 TileCntDecl->setDeclName(
14088 TileIndVars[I] = TileCntDecl;
14096 Stmt *Inner = Body;
14098 auto MakeDimTileSize = [&
SemaRef = this->
SemaRef, &CopyTransformer, &Context,
14099 SizesClause, CurScope](
int I) ->
Expr * {
14100 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14101 if (isa<ConstantExpr>(DimTileSizeExpr))
14102 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14123 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14127 CurScope, {}, BO_LE,
14128 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14131 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14137 for (
int I = NumLoops - 1; I >= 0; --I) {
14140 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters[0]);
14142 Stmt *LoopStmt = LoopStmts[I];
14147 auto MakeTileIVRef = [&
SemaRef = this->
SemaRef, &TileIndVars, I, IVTy,
14150 OrigCntVar->getExprLoc());
14152 auto MakeFloorIVRef = [&
SemaRef = this->
SemaRef, &FloorIndVars, I, IVTy,
14155 OrigCntVar->getExprLoc());
14162 Decl *CounterDecl = TileIndVars[I];
14165 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14173 MakeFloorIVRef(), MakeDimTileSize(I));
14178 NumIterations, EndOfTile.
get());
14183 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
14184 if (!MinTileAndIterSpace.
isUsable())
14188 MakeTileIVRef(), MinTileAndIterSpace.
get());
14194 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeTileIVRef());
14215 BodyParts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14216 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14217 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14218 BodyParts.push_back(Inner);
14220 Inner->getBeginLoc(), Inner->getEndLoc());
14221 Inner =
new (Context)
14228 for (
int I = NumLoops - 1; I >= 0; --I) {
14229 auto &LoopHelper = LoopHelpers[I];
14230 Expr *NumIterations = LoopHelper.NumIterations;
14231 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14237 auto MakeFloorIVRef = [&
SemaRef = this->
SemaRef, &FloorIndVars, I, IVTy,
14248 Decl *CounterDecl = FloorIndVars[I];
14258 MakeFloorIVRef(), NumIterations);
14265 MakeFloorIVRef(), MakeDimTileSize(I));
14269 Inner =
new (Context)
14271 IncrStmt.
get(), Inner, LoopHelper.Init->getBeginLoc(),
14272 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14291 {OMPC_partial, OMPC_full}))
14295 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14297 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14298 assert(!(FullClause && PartialClause) &&
14299 "mutual exclusivity must have been checked before");
14301 constexpr unsigned NumLoops = 1;
14302 Stmt *Body =
nullptr;
14306 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14307 Body, OriginalInits))
14310 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14315 NumGeneratedLoops,
nullptr,
nullptr);
14317 assert(LoopHelpers.size() == NumLoops &&
14318 "Expecting a single-dimensional loop iteration space");
14319 assert(OriginalInits.size() == NumLoops &&
14320 "Expecting a single-dimensional loop iteration space");
14328 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14330 <<
"#pragma omp unroll full";
14338 if (NumGeneratedLoops == 0)
14340 NumGeneratedLoops,
nullptr,
nullptr);
14385 Stmt *LoopStmt =
nullptr;
14390 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14392 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14393 QualType IVTy = IterationVarRef->getType();
14394 assert(LoopHelper.
Counters.size() == 1 &&
14395 "Expecting a single-dimensional loop iteration space");
14396 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14402 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14403 FactorLoc = FactorVal->getExprLoc();
14408 assert(Factor > 0 &&
"Expected positive unroll factor");
14409 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
14421 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14422 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
14423 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
14424 std::string InnerTripCountName =
14425 (Twine(
".unroll_inner.tripcount.") + OrigVarName).str();
14430 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
14436 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14438 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
14444 CaptureVars CopyTransformer(
SemaRef);
14445 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
14468 MakeOuterRef(), MakeFactorExpr());
14473 MakeInnerRef(), EndOfTile.
get());
14478 MakeInnerRef(), MakeNumIterations());
14483 InnerCond1.
get(), InnerCond2.
get());
14489 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeInnerRef());
14495 InnerBodyStmts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14496 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14497 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14498 InnerBodyStmts.push_back(Body);
14502 ForStmt *InnerFor =
new (Context)
14503 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
14519 LoopHintAttr *UnrollHintAttr =
14520 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14521 LoopHintAttr::Numeric, MakeFactorExpr());
14538 MakeOuterRef(), MakeNumIterations());
14545 MakeOuterRef(), MakeFactorExpr());
14550 ForStmt *OuterFor =
new (Context)
14551 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
14556 NumGeneratedLoops, OuterFor,
14570 constexpr unsigned NumLoops = 1;
14571 Stmt *Body =
nullptr;
14575 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14576 Body, OriginalInits))
14585 assert(LoopHelpers.size() == NumLoops &&
14586 "Expecting a single-dimensional loop iteration space");
14587 assert(OriginalInits.size() == NumLoops &&
14588 "Expecting a single-dimensional loop iteration space");
14592 Stmt *LoopStmt =
nullptr;
14597 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14599 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14600 QualType IVTy = IterationVarRef->getType();
14602 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14615 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14617 ForwardIVName += OrigVarName;
14619 ReversedIVName += OrigVarName;
14652 CaptureVars CopyTransformer(
SemaRef);
14653 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
14661 auto MakeForwardRef = [&
SemaRef = this->
SemaRef, ForwardIVDecl, IVTy,
14668 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14669 ReversedIVDecl->setDeclName(
14677 ForwardIVDecl->
getType(), OrigVarLoc);
14681 if (!
Init.isUsable())
14690 MakeForwardRef(), MakeNumIterations());
14699 UO_PreInc, MakeForwardRef());
14710 MakeNumIterations(), One);
14718 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14726 BodyStmts.reserve(LoopHelper.
Updates.size() + 2 +
14727 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14728 BodyStmts.push_back(InitReversed.
get());
14729 llvm::append_range(BodyStmts, LoopHelper.
Updates);
14730 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14731 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14732 BodyStmts.push_back(Body);
14733 auto *ReversedBody =
14738 auto *ReversedFor =
new (Context)
14759 constexpr size_t NumLoops = 2;
14763 Stmt *Body =
nullptr;
14765 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14766 LoopHelpers, Body, OriginalInits))
14772 NumLoops, AStmt,
nullptr,
nullptr);
14774 assert(LoopHelpers.size() == NumLoops &&
14775 "Expecting loop iteration space dimensionaly to match number of "
14777 assert(OriginalInits.size() == NumLoops &&
14778 "Expecting loop iteration space dimensionaly to match number of "
14782 constexpr uint64_t Permutation[] = {1, 0};
14790 for (
auto I : llvm::seq<int>(NumLoops)) {
14793 assert(LoopHelper.
Counters.size() == 1 &&
14794 "Single-dimensional loop iteration space expected");
14795 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14797 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14803 CaptureVars CopyTransformer(
SemaRef);
14808 Stmt *Inner = Body;
14809 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
14811 uint64_t SourceIdx = Permutation[TargetIdx];
14813 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
14814 assert(SourceHelper.
Counters.size() == 1 &&
14815 "Single-dimensional loop iteration space expected");
14816 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.
Counters.front());
14822 "Expected the logical iteration counter to be an integer");
14824 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14829 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
14831 CopyTransformer.TransformExpr(SourceHelper.
NumIterations));
14838 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
14839 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
14840 PermutedCntDecl->setDeclName(
14842 PermutedIndVars[TargetIdx] = PermutedCntDecl;
14843 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
14852 if (!Zero.isUsable())
14858 OrigCntVar->getEndLoc());
14868 MakePermutedRef(), MakeNumIterations());
14877 CurScope, SourceHelper.
Inc->
getExprLoc(), UO_PreInc, MakePermutedRef());
14883 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
14884 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14885 BodyParts.push_back(Inner);
14887 Inner->getBeginLoc(), Inner->getEndLoc());
14888 Inner =
new (Context)
ForStmt(
14889 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
14895 NumLoops, AStmt, Inner,
14909 case OMPC_num_threads:
14918 case OMPC_allocator:
14921 case OMPC_collapse:
14927 case OMPC_num_teams:
14930 case OMPC_thread_limit:
14933 case OMPC_priority:
14945 case OMPC_novariants:
14948 case OMPC_nocontext:
14963 case OMPC_ompx_dyn_cgroup_mem:
14966 case OMPC_grainsize:
14967 case OMPC_num_tasks:
14971 case OMPC_proc_bind:
14972 case OMPC_schedule:
14974 case OMPC_firstprivate:
14975 case OMPC_lastprivate:
14977 case OMPC_reduction:
14978 case OMPC_task_reduction:
14979 case OMPC_in_reduction:
14983 case OMPC_copyprivate:
14986 case OMPC_mergeable:
14987 case OMPC_threadprivate:
14989 case OMPC_allocate:
15006 case OMPC_dist_schedule:
15007 case OMPC_defaultmap:
15012 case OMPC_use_device_ptr:
15013 case OMPC_use_device_addr:
15014 case OMPC_is_device_ptr:
15015 case OMPC_unified_address:
15016 case OMPC_unified_shared_memory:
15017 case OMPC_reverse_offload:
15018 case OMPC_dynamic_allocators:
15019 case OMPC_atomic_default_mem_order:
15020 case OMPC_device_type:
15022 case OMPC_nontemporal:
15025 case OMPC_severity:
15027 case OMPC_inclusive:
15028 case OMPC_exclusive:
15029 case OMPC_uses_allocators:
15030 case OMPC_affinity:
15034 llvm_unreachable(
"Clause is not allowed.");
15047 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15048 "Invalid directive with CKind-clause");
15051 if (NameModifier != OMPD_unknown &&
15052 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15053 return OMPD_unknown;
15072 case OMPD_teams_loop:
15073 case OMPD_target_teams_loop:
15077 case OMPD_target_update:
15078 case OMPD_target_enter_data:
15079 case OMPD_target_exit_data:
15085 case OMPC_num_teams:
15086 case OMPC_thread_limit:
15087 case OMPC_ompx_dyn_cgroup_mem:
15088 if (Leafs[0] == OMPD_target)
15089 return OMPD_target;
15092 if (Leafs[0] == OMPD_target ||
15093 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15094 OMPD_target_enter_data, OMPD_target_exit_data},
15098 case OMPC_novariants:
15099 case OMPC_nocontext:
15100 if (DKind == OMPD_dispatch)
15104 if (DKind == OMPD_metadirective)
15105 return OMPD_metadirective;
15108 return OMPD_unknown;
15121 int InnermostIdx = [&]() {
15122 for (
int I = EndIdx - 1; I >= 0; --I) {
15123 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15131 for (
int I = InnermostIdx - 1; I >= 0; --I) {
15136 if (Regions[0] != OMPD_unknown)
15137 return Regions.back();
15139 return OMPD_unknown;
15144 for (
int I = 0,
E = Leafs.size(); I !=
E; ++I) {
15145 if (Leafs[I] == Dir)
15151 int End = NameModifier == OMPD_unknown ? Leafs.size()
15152 : GetLeafIndex(NameModifier);
15153 return GetEnclosingRegion(End, CKind);
15156 return OMPD_unknown;
15164 Stmt *HelperValStmt =
nullptr;
15167 !
Condition->isInstantiationDependent() &&
15168 !
Condition->containsUnexpandedParameterPack()) {
15173 ValExpr = Val.
get();
15177 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
15178 if (CaptureRegion != OMPD_unknown &&
15181 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15182 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15188 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15189 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15197 Stmt *HelperValStmt =
nullptr;
15200 !
Condition->isInstantiationDependent() &&
15201 !
Condition->containsUnexpandedParameterPack()) {
15211 if (CaptureRegion != OMPD_unknown &&
15214 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15215 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15221 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15232 IntConvertDiagnoser()
15233 : ICEConvertDiagnoser(
false,
false,
true) {}
15236 return S.
Diag(
Loc, diag::err_omp_not_integral) <<
T;
15240 return S.
Diag(
Loc, diag::err_omp_incomplete_type) <<
T;
15245 return S.
Diag(
Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
15254 return S.
Diag(
Loc, diag::err_omp_ambiguous_conversion) <<
T;
15263 llvm_unreachable(
"conversion functions are permitted");
15265 } ConvertDiagnoser;
15271 bool StrictlyPositive,
bool BuildCapture =
false,
15274 Stmt **HelperValStmt =
nullptr) {
15280 if (
Value.isInvalid())
15283 ValExpr =
Value.get();
15285 if (std::optional<llvm::APSInt>
Result =
15287 if (
Result->isSigned() &&
15288 !((!StrictlyPositive &&
Result->isNonNegative()) ||
15289 (StrictlyPositive &&
Result->isStrictlyPositive()))) {
15290 SemaRef.
Diag(
Loc, diag::err_omp_negative_expression_in_clause)
15291 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15300 if (*CaptureRegion != OMPD_unknown &&
15303 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15304 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15315 Expr *ValExpr = NumThreads;
15316 Stmt *HelperValStmt =
nullptr;
15327 if (CaptureRegion != OMPD_unknown &&
15330 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15331 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15336 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15341 bool SuppressExprDiags) {
15350 if (SuppressExprDiags) {
15354 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
15357 llvm_unreachable(
"Diagnostic suppressed");
15369 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
15370 (!StrictlyPositive && !
Result.isNonNegative())) {
15372 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15376 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !
Result.isPowerOf2()) {
15381 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
15383 else if (CKind == OMPC_ordered)
15418 DSAStackTy *Stack) {
15419 if (!Stack->getOMPAllocatorHandleT().isNull())
15426 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15427 <<
"omp_allocator_handle_t";
15432 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15435 bool ErrorFound =
false;
15436 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15437 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
15438 StringRef Allocator =
15439 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15441 auto *VD = dyn_cast_or_null<ValueDecl>(
15461 Stack->setAllocator(AllocatorKind, Res.
get());
15464 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15465 <<
"omp_allocator_handle_t";
15482 if (Allocator.isInvalid())
15485 Allocator.get(),
DSAStack->getOMPAllocatorHandleT(),
15488 if (Allocator.isInvalid())
15514 Expr *NumForLoops) {
15520 if (NumForLoops && LParenLoc.
isValid()) {
15525 NumForLoops = NumForLoopsResult.
get();
15527 NumForLoops =
nullptr;
15531 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
15532 StartLoc, LParenLoc, EndLoc);
15533 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
15544 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15546 case OMPC_proc_bind:
15548 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15550 case OMPC_atomic_default_mem_order:
15553 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15557 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15561 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15565 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15569 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15571 case OMPC_severity:
15574 LParenLoc, EndLoc);
15578 case OMPC_num_threads:
15582 case OMPC_allocator:
15583 case OMPC_collapse:
15584 case OMPC_schedule:
15586 case OMPC_firstprivate:
15587 case OMPC_lastprivate:
15589 case OMPC_reduction:
15590 case OMPC_task_reduction:
15591 case OMPC_in_reduction:
15595 case OMPC_copyprivate:
15599 case OMPC_mergeable:
15600 case OMPC_threadprivate:
15601 case OMPC_allocate:
15618 case OMPC_num_teams:
15619 case OMPC_thread_limit:
15620 case OMPC_priority:
15621 case OMPC_grainsize:
15623 case OMPC_num_tasks:
15625 case OMPC_dist_schedule:
15626 case OMPC_defaultmap:
15631 case OMPC_use_device_ptr:
15632 case OMPC_use_device_addr:
15633 case OMPC_is_device_ptr:
15634 case OMPC_has_device_addr:
15635 case OMPC_unified_address:
15636 case OMPC_unified_shared_memory:
15637 case OMPC_reverse_offload:
15638 case OMPC_dynamic_allocators:
15639 case OMPC_device_type:
15641 case OMPC_nontemporal:
15643 case OMPC_novariants:
15644 case OMPC_nocontext:
15646 case OMPC_inclusive:
15647 case OMPC_exclusive:
15648 case OMPC_uses_allocators:
15649 case OMPC_affinity:
15653 llvm_unreachable(
"Clause is not allowed.");
15662 llvm::raw_svector_ostream Out(Buffer);
15663 unsigned Skipped = Exclude.size();
15664 for (
unsigned I =
First; I <
Last; ++I) {
15665 if (llvm::is_contained(Exclude, I)) {
15670 if (I + Skipped + 2 ==
Last)
15672 else if (I + Skipped + 1 !=
Last)
15675 return std::string(Out.str());
15683 if (Kind == OMP_DEFAULT_unknown) {
15684 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15686 unsigned(OMP_DEFAULT_unknown))
15687 << getOpenMPClauseName(OMPC_default);
15692 case OMP_DEFAULT_none:
15693 DSAStack->setDefaultDSANone(KindKwLoc);
15695 case OMP_DEFAULT_shared:
15696 DSAStack->setDefaultDSAShared(KindKwLoc);
15698 case OMP_DEFAULT_firstprivate:
15699 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15701 case OMP_DEFAULT_private:
15702 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15705 llvm_unreachable(
"DSA unexpected in OpenMP default clause");
15717 if (Kind == OMP_PROC_BIND_unknown) {
15718 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15720 unsigned(OMP_PROC_BIND_master),
15723 ? OMP_PROC_BIND_primary
15724 : OMP_PROC_BIND_spread) +
15726 << getOpenMPClauseName(OMPC_proc_bind);
15729 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
15730 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15732 unsigned(OMP_PROC_BIND_master),
15734 unsigned(OMP_PROC_BIND_spread) + 1)
15735 << getOpenMPClauseName(OMPC_proc_bind);
15744 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15746 OMPC_atomic_default_mem_order, 0,
15748 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15752 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15761 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15764 << getOpenMPClauseName(OMPC_at);
15768 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15777 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15780 << getOpenMPClauseName(OMPC_severity);
15791 assert(ME &&
"NULL expr in Message clause");
15792 if (!isa<StringLiteral>(ME)) {
15794 << getOpenMPClauseName(OMPC_message);
15805 if (Kind != OMPC_ORDER_concurrent ||
15810 "OMPC_ORDER_unknown not greater than 0");
15812 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
15816 << getOpenMPClauseName(OMPC_order);
15821 Diag(MLoc, diag::err_omp_unexpected_clause_value)
15825 << getOpenMPClauseName(OMPC_order);
15827 DSAStack->setRegionHasOrderConcurrent(
true);
15830 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
15831 DSAStack->getCurScope()->setFlags(existingFlags |
15837 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
15846 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
15848 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
15849 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
15851 Except.push_back(OMPC_DEPEND_inoutset);
15852 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15855 << getOpenMPClauseName(OMPC_update);
15859 KindKwLoc, Kind, EndLoc);
15868 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
15878 QualType SizeTy = SizeExpr->getType();
15907 if (!SizeExpr->isInstantiationDependent() && !IsValid)
15908 SizeExpr =
nullptr;
15912 SanitizedSizeExprs);
15928 FactorExpr, OMPC_partial,
true);
15931 FactorExpr = FactorResult.
get();
15946 LParenLoc, EndLoc);
15956 case OMPC_schedule:
15957 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
15958 assert(Argument.size() == NumberOfElements &&
15959 ArgumentLoc.size() == NumberOfElements);
15964 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
15965 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
15968 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
15970 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
15973 case OMPC_dist_schedule:
15976 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
15978 case OMPC_defaultmap:
15979 enum { Modifier, DefaultmapKind };
15983 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
15987 enum { OrderModifier, OrderKind };
15991 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
15994 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
15997 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
15999 case OMPC_grainsize:
16000 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16001 "Modifier for grainsize clause and its location are expected.");
16004 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16006 case OMPC_num_tasks:
16007 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16008 "Modifier for num_tasks clause and its location are expected.");
16011 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16014 case OMPC_num_threads:
16018 case OMPC_allocator:
16019 case OMPC_collapse:
16021 case OMPC_proc_bind:
16023 case OMPC_firstprivate:
16024 case OMPC_lastprivate:
16026 case OMPC_reduction:
16027 case OMPC_task_reduction:
16028 case OMPC_in_reduction:
16032 case OMPC_copyprivate:
16036 case OMPC_mergeable:
16037 case OMPC_threadprivate:
16038 case OMPC_allocate:
16055 case OMPC_num_teams:
16056 case OMPC_thread_limit:
16057 case OMPC_priority:
16064 case OMPC_use_device_ptr:
16065 case OMPC_use_device_addr:
16066 case OMPC_is_device_ptr:
16067 case OMPC_has_device_addr:
16068 case OMPC_unified_address:
16069 case OMPC_unified_shared_memory:
16070 case OMPC_reverse_offload:
16071 case OMPC_dynamic_allocators:
16072 case OMPC_atomic_default_mem_order:
16073 case OMPC_device_type:
16075 case OMPC_nontemporal:
16077 case OMPC_severity:
16080 case OMPC_novariants:
16081 case OMPC_nocontext:
16083 case OMPC_inclusive:
16084 case OMPC_exclusive:
16085 case OMPC_uses_allocators:
16086 case OMPC_affinity:
16090 llvm_unreachable(
"Clause is not allowed.");
16101 Excluded.push_back(M2);
16102 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16103 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16104 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16105 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16106 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16111 << getOpenMPClauseName(OMPC_schedule);
16129 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16130 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16131 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16132 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16133 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16139 std::string Values;
16149 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16150 << Values << getOpenMPClauseName(OMPC_schedule);
16158 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16159 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16160 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16161 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16162 diag::err_omp_schedule_nonmonotonic_static);
16165 Expr *ValExpr = ChunkSize;
16166 Stmt *HelperValStmt =
nullptr;
16177 ValExpr = Val.
get();
16182 if (std::optional<llvm::APSInt>
Result =
16184 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
16185 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16190 DSAStack->getCurrentDirective(), OMPC_schedule,
16194 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16195 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16203 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16220 case OMPC_mergeable:
16268 case OMPC_unified_address:
16271 case OMPC_unified_shared_memory:
16274 case OMPC_reverse_offload:
16277 case OMPC_dynamic_allocators:
16291 case OMPC_ompx_bare:
16296 case OMPC_num_threads:
16300 case OMPC_allocator:
16301 case OMPC_collapse:
16302 case OMPC_schedule:
16304 case OMPC_firstprivate:
16305 case OMPC_lastprivate:
16307 case OMPC_reduction:
16308 case OMPC_task_reduction:
16309 case OMPC_in_reduction:
16313 case OMPC_copyprivate:
16315 case OMPC_proc_bind:
16316 case OMPC_threadprivate:
16317 case OMPC_allocate:
16323 case OMPC_num_teams:
16324 case OMPC_thread_limit:
16325 case OMPC_priority:
16326 case OMPC_grainsize:
16327 case OMPC_num_tasks:
16329 case OMPC_dist_schedule:
16330 case OMPC_defaultmap:
16335 case OMPC_use_device_ptr:
16336 case OMPC_use_device_addr:
16337 case OMPC_is_device_ptr:
16338 case OMPC_has_device_addr:
16339 case OMPC_atomic_default_mem_order:
16340 case OMPC_device_type:
16342 case OMPC_nontemporal:
16345 case OMPC_severity:
16347 case OMPC_novariants:
16348 case OMPC_nocontext:
16350 case OMPC_inclusive:
16351 case OMPC_exclusive:
16352 case OMPC_uses_allocators:
16353 case OMPC_affinity:
16355 case OMPC_ompx_dyn_cgroup_mem:
16357 llvm_unreachable(
"Clause is not allowed.");
16416 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16497 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16498 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
16499 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16500 <<
Expected << getOpenMPDirectiveName(OMPD_interop);
16513 bool HasInitClause =
false;
16514 bool IsTargetSync =
false;
16518 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
16519 HasInitClause =
true;
16520 if (InitClause->getIsTargetSync())
16521 IsTargetSync =
true;
16522 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
16526 if (DependClause && HasInitClause && !IsTargetSync) {
16527 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16541 if (ClauseKind == OMPC_init) {
16542 auto *
E = cast<OMPInitClause>(
C)->getInteropVar();
16544 }
else if (ClauseKind == OMPC_use) {
16545 auto *
E = cast<OMPUseClause>(
C)->getInteropVar();
16547 }
else if (ClauseKind == OMPC_destroy) {
16548 auto *
E = cast<OMPDestroyClause>(
C)->getInteropVar();
16553 if (!InteropVars.insert(
DeclResult.first).second) {
16554 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16570 Expr *RefExpr = InteropVarExpr;
16573 false,
"omp_interop_t");
16584 bool HasError =
false;
16590 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
16591 InteropType =
QualType(TD->getTypeForDecl(), 0);
16600 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
16601 <<
"omp_interop_t";
16607 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16613 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16615 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
16637 if (isa<StringLiteral>(
E))
16644 StartLoc, LParenLoc, VarLoc, EndLoc);
16657 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16666 DSAStack->getCurrentDirective() == OMPD_depobj) {
16667 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16668 << getOpenMPClauseName(OMPC_destroy)
16669 << getOpenMPDirectiveName(OMPD_depobj);
16685 Stmt *HelperValStmt =
nullptr;
16688 !
Condition->isInstantiationDependent() &&
16689 !
Condition->containsUnexpandedParameterPack()) {
16699 if (CaptureRegion != OMPD_unknown &&
16702 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16703 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16709 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16717 Stmt *HelperValStmt =
nullptr;
16720 !
Condition->isInstantiationDependent() &&
16721 !
Condition->containsUnexpandedParameterPack()) {
16731 if (CaptureRegion != OMPD_unknown &&
16734 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16735 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16741 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16748 Expr *ValExpr = ThreadID;
16749 Stmt *HelperValStmt =
nullptr;
16754 if (CaptureRegion != OMPD_unknown &&
16757 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16758 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16763 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16774 int ExtraModifier =
Data.ExtraModifier;
16781 case OMPC_firstprivate:
16784 case OMPC_lastprivate:
16786 "Unexpected lastprivate modifier.");
16789 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
16794 case OMPC_reduction:
16796 "Unexpected lastprivate modifier.");
16799 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
16800 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
16802 case OMPC_task_reduction:
16804 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16805 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
16807 case OMPC_in_reduction:
16809 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16810 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
16814 "Unexpected linear modifier.");
16816 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
16818 ColonLoc,
Data.StepModifierLoc, EndLoc);
16822 LParenLoc, ColonLoc, EndLoc);
16827 case OMPC_copyprivate:
16835 "Unexpected depend modifier.");
16838 ColonLoc,
Data.OmpAllMemoryLoc},
16839 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
16843 "Unexpected map modifier.");
16845 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
16846 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
16848 ExtraModifierLoc, ColonLoc, VarList, Locs);
16853 Data.ReductionOrMapperIdScopeSpec,
16854 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
16858 Data.ReductionOrMapperIdScopeSpec,
16859 Data.ReductionOrMapperId, ColonLoc, VarList,
16862 case OMPC_use_device_ptr:
16865 case OMPC_use_device_addr:
16868 case OMPC_is_device_ptr:
16871 case OMPC_has_device_addr:
16874 case OMPC_allocate:
16876 LParenLoc, ColonLoc, EndLoc);
16878 case OMPC_nontemporal:
16881 case OMPC_inclusive:
16884 case OMPC_exclusive:
16887 case OMPC_affinity:
16889 Data.DepModOrTailExpr, VarList);
16891 case OMPC_doacross:
16894 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
16899 case OMPC_num_threads:
16903 case OMPC_allocator:
16904 case OMPC_collapse:
16906 case OMPC_proc_bind:
16907 case OMPC_schedule:
16911 case OMPC_mergeable:
16912 case OMPC_threadprivate:
16926 case OMPC_num_teams:
16927 case OMPC_thread_limit:
16928 case OMPC_priority:
16929 case OMPC_grainsize:
16931 case OMPC_num_tasks:
16933 case OMPC_dist_schedule:
16934 case OMPC_defaultmap:
16937 case OMPC_unified_address:
16938 case OMPC_unified_shared_memory:
16939 case OMPC_reverse_offload:
16940 case OMPC_dynamic_allocators:
16941 case OMPC_atomic_default_mem_order:
16942 case OMPC_device_type:
16946 case OMPC_severity:
16949 case OMPC_novariants:
16950 case OMPC_nocontext:
16952 case OMPC_uses_allocators:
16956 llvm_unreachable(
"Clause is not allowed.");
16987 bool IsImplicitClause =
16989 for (
Expr *RefExpr : VarList) {
16990 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
16993 Expr *SimpleRefExpr = RefExpr;
16997 Vars.push_back(RefExpr);
16998 PrivateCopies.push_back(
nullptr);
17005 auto *VD = dyn_cast<VarDecl>(
D);
17011 diag::err_omp_private_incomplete_type))
17013 Type =
Type.getNonReferenceType();
17033 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17034 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17035 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17036 << getOpenMPClauseName(OMPC_private);
17045 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17046 << getOpenMPClauseName(OMPC_private) <<
Type
17047 << getOpenMPDirectiveName(CurrDir);
17048 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17051 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17066 CurrDir == OMPD_target) {
17068 if (
DSAStack->checkMappableExprComponentListsForDecl(
17072 ConflictKind = WhereFoundClauseKind;
17075 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17076 << getOpenMPClauseName(OMPC_private)
17077 << getOpenMPClauseName(ConflictKind)
17078 << getOpenMPDirectiveName(CurrDir);
17097 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17106 auto *FD = dyn_cast<FieldDecl>(
D);
17110 RefExpr->getExprLoc());
17114 if (!IsImplicitClause)
17115 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17117 ? RefExpr->IgnoreParens()
17119 PrivateCopies.push_back(VDPrivateRefExpr);
17126 Vars, PrivateCopies);
17137 bool IsImplicitClause =
17141 for (
Expr *RefExpr : VarList) {
17142 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
17145 Expr *SimpleRefExpr = RefExpr;
17149 Vars.push_back(RefExpr);
17150 PrivateCopies.push_back(
nullptr);
17151 Inits.push_back(
nullptr);
17157 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17159 auto *VD = dyn_cast<VarDecl>(
D);
17165 diag::err_omp_firstprivate_incomplete_type))
17167 Type =
Type.getNonReferenceType();
17177 DSAStackTy::DSAVarData TopDVar;
17178 if (!IsImplicitClause) {
17179 DSAStackTy::DSAVarData DVar =
17191 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17193 DVar.CKind != OMPC_lastprivate) &&
17195 Diag(ELoc, diag::err_omp_wrong_dsa)
17196 << getOpenMPClauseName(DVar.CKind)
17197 << getOpenMPClauseName(OMPC_firstprivate);
17213 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17214 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17215 Diag(ELoc, diag::err_omp_wrong_dsa)
17216 << getOpenMPClauseName(DVar.CKind)
17217 << getOpenMPClauseName(OMPC_firstprivate);
17241 DVar =
DSAStack->getImplicitDSA(
D,
true);
17242 if (DVar.CKind != OMPC_shared &&
17245 DVar.DKind == OMPD_unknown)) {
17246 Diag(ELoc, diag::err_omp_required_access)
17247 << getOpenMPClauseName(OMPC_firstprivate)
17248 << getOpenMPClauseName(OMPC_shared);
17268 return C == OMPC_reduction && !AppliedToPointee;
17276 if (DVar.CKind == OMPC_reduction &&
17280 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17281 << getOpenMPDirectiveName(DVar.DKind);
17297 CurrDir == OMPD_target) {
17299 if (
DSAStack->checkMappableExprComponentListsForDecl(
17304 ConflictKind = WhereFoundClauseKind;
17307 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17308 << getOpenMPClauseName(OMPC_firstprivate)
17309 << getOpenMPClauseName(ConflictKind)
17310 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17320 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17321 << getOpenMPClauseName(OMPC_firstprivate) <<
Type
17322 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17323 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17326 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17335 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17341 Expr *VDInitRefExpr =
nullptr;
17351 ElemType,
".firstprivate.temp");
17366 ".firstprivate.temp");
17368 RefExpr->getExprLoc());
17374 if (IsImplicitClause) {
17375 Diag(RefExpr->getExprLoc(),
17376 diag::note_omp_task_predetermined_firstprivate_here);
17383 RefExpr->getExprLoc());
17386 if (TopDVar.CKind == OMPC_lastprivate) {
17387 Ref = TopDVar.PrivateCopy;
17389 auto *FD = dyn_cast<FieldDecl>(
D);
17394 RefExpr->getExprLoc());
17398 ExprCaptures.push_back(Ref->
getDecl());
17401 if (!IsImplicitClause)
17402 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17404 ? RefExpr->IgnoreParens()
17406 PrivateCopies.push_back(VDPrivateRefExpr);
17407 Inits.push_back(VDInitRefExpr);
17414 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17423 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
17424 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17427 << getOpenMPClauseName(OMPC_lastprivate);
17437 for (
Expr *RefExpr : VarList) {
17438 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17441 Expr *SimpleRefExpr = RefExpr;
17445 Vars.push_back(RefExpr);
17446 SrcExprs.push_back(
nullptr);
17447 DstExprs.push_back(
nullptr);
17448 AssignmentOps.push_back(
nullptr);
17455 auto *VD = dyn_cast<VarDecl>(
D);
17461 diag::err_omp_lastprivate_incomplete_type))
17463 Type =
Type.getNonReferenceType();
17480 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17481 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17484 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17498 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17499 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17501 DVar.CKind != OMPC_firstprivate) &&
17502 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
17503 Diag(ELoc, diag::err_omp_wrong_dsa)
17504 << getOpenMPClauseName(DVar.CKind)
17505 << getOpenMPClauseName(OMPC_lastprivate);
17516 DSAStackTy::DSAVarData TopDVar = DVar;
17520 DVar =
DSAStack->getImplicitDSA(
D,
true);
17521 if (DVar.CKind != OMPC_shared) {
17522 Diag(ELoc, diag::err_omp_required_access)
17523 << getOpenMPClauseName(OMPC_lastprivate)
17524 << getOpenMPClauseName(OMPC_shared);
17540 Type.getUnqualifiedType(),
".lastprivate.src",
17551 PseudoDstExpr, PseudoSrcExpr);
17561 if (TopDVar.CKind == OMPC_firstprivate) {
17562 Ref = TopDVar.PrivateCopy;
17566 ExprCaptures.push_back(Ref->
getDecl());
17568 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17576 SimpleRefExpr, RefRes.
get());
17579 ExprPostUpdates.push_back(
17583 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17585 ? RefExpr->IgnoreParens()
17587 SrcExprs.push_back(PseudoSrcExpr);
17588 DstExprs.push_back(PseudoDstExpr);
17589 AssignmentOps.push_back(AssignmentOp.
get());
17596 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17597 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17607 for (
Expr *RefExpr : VarList) {
17608 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17611 Expr *SimpleRefExpr = RefExpr;
17615 Vars.push_back(RefExpr);
17621 auto *VD = dyn_cast<VarDecl>(
D);
17629 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17630 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17632 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17633 << getOpenMPClauseName(OMPC_shared);
17642 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17644 ? RefExpr->IgnoreParens()
17656class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
17661 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
17662 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
17663 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17665 if (DVar.CKind != OMPC_unknown)
17667 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17674 return DVarPrivate.CKind != OMPC_unknown;
17678 bool VisitStmt(
Stmt *S) {
17679 for (
Stmt *Child : S->children()) {
17680 if (Child && Visit(Child))
17685 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17692class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
17699 : BaseTransform(SemaRef),
Field(
FieldDecl), CapturedExpr(nullptr) {}
17703 E->getMemberDecl() == Field) {
17705 return CapturedExpr;
17707 return BaseTransform::TransformMemberExpr(
E);
17709 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
17713template <
typename T,
typename U>
17716 for (
U &
Set : Lookups) {
17717 for (
auto *
D :
Set) {
17718 if (
T Res = Gen(cast<ValueDecl>(
D)))
17733 auto ND = cast<NamedDecl>(RD);
17751 AssociatedClasses);
17764 for (
auto *NS : AssociatedNamespaces) {
17777 for (
auto *
D : R) {
17778 auto *Underlying =
D;
17779 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
17780 Underlying = USD->getTargetDecl();
17782 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
17783 !isa<OMPDeclareMapperDecl>(Underlying))
17790 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
17791 Underlying = USD->getTargetDecl();
17793 Lookups.emplace_back();
17794 Lookups.back().addDecl(Underlying);
17814 S = S->getParent();
17815 }
while (S && !S->isDeclScope(
D));
17817 S = S->getParent();
17818 Lookups.emplace_back();
17819 Lookups.back().append(Lookup.
begin(), Lookup.
end());
17822 }
else if (
auto *ULE =
17823 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
17825 Decl *PrevD =
nullptr;
17829 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(
D))
17830 Lookups.back().addDecl(DRD);
17837 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
17838 return !D->isInvalidDecl() &&
17839 (D->getType()->isDependentType() ||
17840 D->getType()->isInstantiationDependentType() ||
17841 D->getType()->containsUnexpandedParameterPack());
17854 true, ResSet.
begin(), ResSet.
end(),
false);
17875 TyRec->getDecl()->getDefinition()) {
17878 if (Lookup.
empty()) {
17879 Lookups.emplace_back();
17880 Lookups.back().append(Lookup.
begin(), Lookup.
end());
17887 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
17897 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
17921 if (ReductionIdScopeSpec.
isSet()) {
17922 SemaRef.
Diag(
Loc, diag::err_omp_not_resolved_reduction_identifier)
17931struct ReductionData {
17956 unsigned RedModifier = 0;
17957 ReductionData() =
delete;
17959 ReductionData(
unsigned Size,
unsigned Modifier = 0) : RedModifier(Modifier) {
17960 Vars.reserve(Size);
17961 Privates.reserve(Size);
17962 LHSs.reserve(Size);
17963 RHSs.reserve(Size);
17964 ReductionOps.reserve(Size);
17965 if (RedModifier == OMPC_REDUCTION_inscan) {
17966 InscanCopyOps.reserve(Size);
17967 InscanCopyArrayTemps.reserve(Size);
17968 InscanCopyArrayElems.reserve(Size);
17970 TaskgroupDescriptors.reserve(Size);
17971 ExprCaptures.reserve(Size);
17972 ExprPostUpdates.reserve(Size);
17976 void push(
Expr *Item,
Expr *ReductionOp) {
17977 Vars.emplace_back(Item);
17978 Privates.emplace_back(
nullptr);
17979 LHSs.emplace_back(
nullptr);
17980 RHSs.emplace_back(
nullptr);
17981 ReductionOps.emplace_back(ReductionOp);
17982 TaskgroupDescriptors.emplace_back(
nullptr);
17983 if (RedModifier == OMPC_REDUCTION_inscan) {
17984 InscanCopyOps.push_back(
nullptr);
17985 InscanCopyArrayTemps.push_back(
nullptr);
17986 InscanCopyArrayElems.push_back(
nullptr);
17991 Expr *TaskgroupDescriptor,
Expr *CopyOp,
Expr *CopyArrayTemp,
17992 Expr *CopyArrayElem) {
17993 Vars.emplace_back(Item);
17994 Privates.emplace_back(Private);
17995 LHSs.emplace_back(LHS);
17996 RHSs.emplace_back(RHS);
17997 ReductionOps.emplace_back(ReductionOp);
17998 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
17999 if (RedModifier == OMPC_REDUCTION_inscan) {
18000 InscanCopyOps.push_back(CopyOp);
18001 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18002 InscanCopyArrayElems.push_back(CopyArrayElem);
18004 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
18005 CopyArrayElem ==
nullptr &&
18006 "Copy operation must be used for inscan reductions only.");
18016 if (Length ==
nullptr) {
18023 SingleElement =
true;
18024 ArraySizes.push_back(llvm::APSInt::get(1));
18027 if (!Length->EvaluateAsInt(
Result, Context))
18030 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18031 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18032 ArraySizes.push_back(ConstantLengthValue);
18040 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
18041 Length = TempOASE->getLength();
18042 if (Length ==
nullptr) {
18049 ArraySizes.push_back(llvm::APSInt::get(1));
18052 if (!Length->EvaluateAsInt(
Result, Context))
18055 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18056 if (ConstantLengthValue.getSExtValue() != 1)
18059 ArraySizes.push_back(ConstantLengthValue);
18061 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18065 if (!SingleElement) {
18066 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
18068 ArraySizes.push_back(llvm::APSInt::get(1));
18069 Base = TempASE->getBase()->IgnoreParenImpCasts();
18081 return BO_AddAssign;
18083 return BO_MulAssign;
18085 return BO_AndAssign;
18087 return BO_OrAssign;
18089 return BO_XorAssign;
18145 case OO_Array_Delete:
18154 case OO_GreaterEqual:
18156 case OO_MinusEqual:
18158 case OO_SlashEqual:
18159 case OO_PercentEqual:
18160 case OO_CaretEqual:
18164 case OO_GreaterGreater:
18165 case OO_LessLessEqual:
18166 case OO_GreaterGreaterEqual:
18167 case OO_EqualEqual:
18168 case OO_ExclaimEqual:
18171 case OO_MinusMinus:
18177 case OO_Conditional:
18180 llvm_unreachable(
"Unexpected reduction identifier");
18183 if (II->isStr(
"max"))
18185 else if (II->isStr(
"min"))
18193 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
18194 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18197 if (ReductionIdScopeSpec.
isValid())
18203 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18204 bool FirstIter =
true;
18205 for (
Expr *RefExpr : VarList) {
18206 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
18214 if (!FirstIter && IR != ER)
18219 Expr *SimpleRefExpr = RefExpr;
18228 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18229 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18230 Expr *ReductionOp =
nullptr;
18232 (DeclareReductionRef.
isUnset() ||
18233 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get())))
18234 ReductionOp = DeclareReductionRef.
get();
18236 RD.push(RefExpr, ReductionOp);
18242 Expr *TaskgroupDescriptor =
nullptr;
18244 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18245 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18247 Type = ASE->getType().getNonReferenceType();
18252 Type = ATy->getElementType();
18255 Type =
Type.getNonReferenceType();
18259 auto *VD = dyn_cast<VarDecl>(
D);
18265 diag::err_omp_reduction_incomplete_type))
18271 false, ASE || OASE))
18278 if (!ASE && !OASE) {
18280 VarDecl *VDDef = VD->getDefinition();
18282 DSARefChecker Check(Stack);
18283 if (Check.Visit(VDDef->
getInit())) {
18284 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18285 << getOpenMPClauseName(ClauseKind) << ERange;
18303 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18304 if (DVar.CKind == OMPC_reduction) {
18305 S.
Diag(ELoc, diag::err_omp_once_referenced)
18306 << getOpenMPClauseName(ClauseKind);
18308 S.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18311 if (DVar.CKind != OMPC_unknown) {
18312 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18313 << getOpenMPClauseName(DVar.CKind)
18314 << getOpenMPClauseName(OMPC_reduction);
18326 DVar = Stack->getImplicitDSA(
D,
true);
18327 if (DVar.CKind != OMPC_shared) {
18328 S.
Diag(ELoc, diag::err_omp_required_access)
18329 << getOpenMPClauseName(OMPC_reduction)
18330 << getOpenMPClauseName(OMPC_shared);
18338 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18339 if (DVar.CKind == OMPC_threadprivate) {
18340 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18341 << getOpenMPClauseName(DVar.CKind)
18342 << getOpenMPClauseName(OMPC_reduction);
18352 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18353 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18357 (DeclareReductionRef.
isUnset() ||
18358 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get()))) {
18359 RD.push(RefExpr, DeclareReductionRef.
get());
18362 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
18366 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18367 <<
Type << ReductionIdRange;
18370 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18371 <<
Type << ReductionIdRange;
18383 if (DeclareReductionRef.
isUnset()) {
18384 if ((BOK == BO_GT || BOK == BO_LT) &&
18387 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18388 << getOpenMPClauseName(ClauseKind) << S.
getLangOpts().CPlusPlus;
18389 if (!ASE && !OASE) {
18390 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18393 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18398 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18400 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18401 << getOpenMPClauseName(ClauseKind);
18402 if (!ASE && !OASE) {
18403 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18406 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18413 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
18422 bool ConstantLengthOASE =
false;
18424 bool SingleElement;
18427 Context, OASE, SingleElement, ArraySizes);
18430 if (ConstantLengthOASE && !SingleElement) {
18431 for (llvm::APSInt &Size : ArraySizes)
18438 if ((OASE && !ConstantLengthOASE) ||
18440 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18443 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18444 S.
Diag(ELoc, diag::note_vla_unsupported);
18447 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18448 S.
targetDiag(ELoc, diag::note_vla_unsupported);
18461 }
else if (!ASE && !OASE &&
18463 PrivateTy =
D->getType().getNonReferenceType();
18469 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
18474 if (DeclareReductionRef.
isUsable()) {
18476 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18477 if (DRD->getInitializer()) {
18503 Type = ComplexTy->getElementType();
18505 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18512 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18534 llvm::APInt InitValue =
18535 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18536 : llvm::APInt::getMinValue(Size)
18537 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18538 : llvm::APInt::getMaxValue(Size);
18549 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18580 llvm_unreachable(
"Unexpected reduction operation");
18589 }
else if (!
Init) {
18599 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18600 <<
Type << ReductionIdRange;
18601 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18604 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18610 if (DeclareReductionRef.
isUsable()) {
18615 if (!BasePath.empty()) {
18619 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
18622 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
18626 QualType Params[] = {PtrRedTy, PtrRedTy};
18641 CombBOK, LHSDRE, RHSDRE);
18648 if (BOK != BO_LT && BOK != BO_GT) {
18651 BO_Assign, LHSDRE, ReductionOp.
get());
18653 auto *ConditionalOp =
new (Context)
18658 BO_Assign, LHSDRE, ConditionalOp);
18671 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18672 if (ClauseKind == OMPC_reduction &&
18673 RD.RedModifier == OMPC_REDUCTION_inscan) {
18675 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18685 if (Stack->getCurrentDirective() == OMPD_simd ||
18723 if (ClauseKind == OMPC_in_reduction) {
18726 const Expr *ParentReductionOp =
nullptr;
18727 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
18728 DSAStackTy::DSAVarData ParentBOKDSA =
18729 Stack->getTopMostTaskgroupReductionData(
D, ParentSR, ParentBOK,
18731 DSAStackTy::DSAVarData ParentReductionOpDSA =
18732 Stack->getTopMostTaskgroupReductionData(
18733 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
18734 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
18735 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
18736 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
18737 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
18738 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
18739 bool EmitError =
true;
18740 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
18741 llvm::FoldingSetNodeID RedId, ParentRedId;
18742 ParentReductionOp->
Profile(ParentRedId, Context,
true);
18743 DeclareReductionRef.
get()->
Profile(RedId, Context,
18745 EmitError = RedId != ParentRedId;
18749 diag::err_omp_reduction_identifier_mismatch)
18750 << ReductionIdRange << RefExpr->getSourceRange();
18752 diag::note_omp_previous_reduction_identifier)
18754 << (IsParentBOK ? ParentBOKDSA.RefExpr
18755 : ParentReductionOpDSA.RefExpr)
18756 ->getSourceRange();
18760 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
18767 TransformExprToCaptures RebuildToCapture(S,
D);
18769 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
18770 Ref = RebuildToCapture.getCapturedExpr();
18775 RD.ExprCaptures.emplace_back(Ref->
getDecl());
18781 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18786 Stack->getCurrentDirective() == OMPD_taskgroup) {
18787 S.
Diag(RefExpr->getExprLoc(),
18788 diag::err_omp_reduction_non_addressable_expression)
18789 << RefExpr->getSourceRange();
18792 RD.ExprPostUpdates.emplace_back(
18799 unsigned Modifier = RD.RedModifier;
18802 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
18803 Modifier = OMPC_REDUCTION_task;
18804 Stack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
18806 if (Modifier == OMPC_REDUCTION_task &&
18807 (CurrDir == OMPD_taskgroup ||
18811 if (DeclareReductionRef.
isUsable())
18812 Stack->addTaskgroupReductionData(
D, ReductionIdRange,
18813 DeclareReductionRef.
get());
18815 Stack->addTaskgroupReductionData(
D, ReductionIdRange, BOK);
18817 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
18818 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
18819 TempArrayElem.
get());
18821 return RD.Vars.empty();
18831 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
18834 << getOpenMPClauseName(OMPC_reduction);
18842 if (Modifier == OMPC_REDUCTION_inscan &&
18843 (
DSAStack->getCurrentDirective() != OMPD_for &&
18844 DSAStack->getCurrentDirective() != OMPD_for_simd &&
18845 DSAStack->getCurrentDirective() != OMPD_simd &&
18846 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
18847 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
18848 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
18852 ReductionData RD(VarList.size(), Modifier);
18854 StartLoc, LParenLoc, ColonLoc, EndLoc,
18855 ReductionIdScopeSpec, ReductionId,
18856 UnresolvedReductions, RD))
18860 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
18863 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
18864 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
18874 ReductionData RD(VarList.size());
18876 VarList, StartLoc, LParenLoc, ColonLoc,
18877 EndLoc, ReductionIdScopeSpec, ReductionId,
18878 UnresolvedReductions, RD))
18882 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
18884 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
18894 ReductionData RD(VarList.size());
18896 StartLoc, LParenLoc, ColonLoc, EndLoc,
18897 ReductionIdScopeSpec, ReductionId,
18898 UnresolvedReductions, RD))
18902 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
18904 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
18913 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
18923 const auto *VD = dyn_cast_or_null<VarDecl>(
D);
18926 diag::err_omp_linear_incomplete_type))
18928 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
18930 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
18934 Type =
Type.getNonReferenceType();
18941 if (!IsDeclareSimd &&
18946 Type =
Type.getUnqualifiedType().getCanonicalType();
18947 const auto *Ty =
Type.getTypePtrOrNull();
18948 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
18949 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
18950 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
18952 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
18955 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18978 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
18980 LinKind = OMPC_LINEAR_val;
18981 for (
Expr *RefExpr : VarList) {
18982 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
18985 Expr *SimpleRefExpr = RefExpr;
18989 Vars.push_back(RefExpr);
18990 Privates.push_back(
nullptr);
18991 Inits.push_back(
nullptr);
18998 auto *VD = dyn_cast<VarDecl>(
D);
19004 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
19005 if (DVar.RefExpr) {
19006 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19007 << getOpenMPClauseName(OMPC_linear);
19014 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19020 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
19029 ExprCaptures.push_back(Ref->
getDecl());
19036 SimpleRefExpr, RefRes.
get());
19039 ExprPostUpdates.push_back(
19044 if (LinKind == OMPC_LINEAR_uval)
19045 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19047 InitExpr = VD ? SimpleRefExpr : Ref;
19053 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19055 ? RefExpr->IgnoreParens()
19057 Privates.push_back(PrivateRef);
19058 Inits.push_back(InitRef);
19064 Expr *StepExpr = Step;
19065 Expr *CalcStepExpr =
nullptr;
19073 StepExpr = Val.
get();
19087 if (std::optional<llvm::APSInt>
Result =
19089 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
19090 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19091 << Vars[0] << (Vars.size() > 1);
19095 CalcStepExpr = CalcStep.
get();
19100 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19101 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19107 Expr *NumIterations,
Sema &SemaRef,
19108 Scope *S, DSAStackTy *Stack) {
19120 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19121 bool HasErrors =
false;
19122 auto CurInit = Clause.
inits().begin();
19123 auto CurPrivate = Clause.
privates().begin();
19128 Expr *SimpleRefExpr = RefExpr;
19129 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19131 if (Res.second || !
D) {
19132 Updates.push_back(
nullptr);
19133 Finals.push_back(
nullptr);
19137 auto &&Info = Stack->isLoopControlVariable(
D);
19144 diag::err_omp_linear_distribute_var_non_loop_iteration);
19145 Updates.push_back(
nullptr);
19146 Finals.push_back(
nullptr);
19150 Expr *InitExpr = *CurInit;
19153 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19155 if (LinKind == OMPC_LINEAR_uval)
19156 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19160 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19167 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19178 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19181 Final = *CurPrivate;
19185 if (!
Update.isUsable() || !Final.isUsable()) {
19186 Updates.push_back(
nullptr);
19187 Finals.push_back(
nullptr);
19188 UsedExprs.push_back(
nullptr);
19191 Updates.push_back(
Update.get());
19192 Finals.push_back(Final.get());
19194 UsedExprs.push_back(SimpleRefExpr);
19200 UsedExprs.push_back(S);
19202 UsedExprs.append(Clause.
varlist_size() + 1 - UsedExprs.size(),
nullptr);
19213 for (
Expr *RefExpr : VarList) {
19214 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19217 Expr *SimpleRefExpr = RefExpr;
19221 Vars.push_back(RefExpr);
19228 auto *VD = dyn_cast<VarDecl>(
D);
19236 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19238 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19241 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19248 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(
D, SimpleRefExpr)) {
19249 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19250 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19251 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19252 << getOpenMPClauseName(OMPC_aligned);
19260 .DefaultFunctionArrayConversion(
19261 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19270 if (Alignment !=
nullptr) {
19275 Alignment = AlignResult.
get();
19281 ColonLoc, EndLoc, Vars, Alignment);
19292 for (
Expr *RefExpr : VarList) {
19293 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
19294 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19296 Vars.push_back(RefExpr);
19297 SrcExprs.push_back(
nullptr);
19298 DstExprs.push_back(
nullptr);
19299 AssignmentOps.push_back(
nullptr);
19308 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19309 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19310 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19311 << 0 << RefExpr->getSourceRange();
19315 Decl *
D = DE->getDecl();
19316 auto *VD = cast<VarDecl>(
D);
19321 Vars.push_back(DE);
19322 SrcExprs.push_back(
nullptr);
19323 DstExprs.push_back(
nullptr);
19324 AssignmentOps.push_back(
nullptr);
19330 if (!
DSAStack->isThreadPrivate(VD)) {
19331 Diag(ELoc, diag::err_omp_required_access)
19332 << getOpenMPClauseName(OMPC_copyin)
19333 << getOpenMPDirectiveName(OMPD_threadprivate);
19357 PseudoDstExpr, PseudoSrcExpr);
19366 DSAStack->addDSA(VD, DE, OMPC_copyin);
19367 Vars.push_back(DE);
19368 SrcExprs.push_back(PseudoSrcExpr);
19369 DstExprs.push_back(PseudoDstExpr);
19370 AssignmentOps.push_back(AssignmentOp.
get());
19377 Vars, SrcExprs, DstExprs, AssignmentOps);
19388 for (
Expr *RefExpr : VarList) {
19389 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19392 Expr *SimpleRefExpr = RefExpr;
19396 Vars.push_back(RefExpr);
19397 SrcExprs.push_back(
nullptr);
19398 DstExprs.push_back(
nullptr);
19399 AssignmentOps.push_back(
nullptr);
19406 auto *VD = dyn_cast<VarDecl>(
D);
19411 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
19412 DSAStackTy::DSAVarData DVar =
19414 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19416 Diag(ELoc, diag::err_omp_wrong_dsa)
19417 << getOpenMPClauseName(DVar.CKind)
19418 << getOpenMPClauseName(OMPC_copyprivate);
19426 if (DVar.CKind == OMPC_unknown) {
19427 DVar =
DSAStack->getImplicitDSA(
D,
false);
19428 if (DVar.CKind == OMPC_shared) {
19429 Diag(ELoc, diag::err_omp_required_access)
19430 << getOpenMPClauseName(OMPC_copyprivate)
19431 <<
"threadprivate or private in the enclosing context";
19440 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19441 << getOpenMPClauseName(OMPC_copyprivate) <<
Type
19442 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
19443 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19446 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19467 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19479 VD ? RefExpr->IgnoreParens()
19481 SrcExprs.push_back(PseudoSrcExpr);
19482 DstExprs.push_back(PseudoDstExpr);
19483 AssignmentOps.push_back(AssignmentOp.
get());
19490 EndLoc, Vars, SrcExprs, DstExprs,
19498 if (VarList.empty())
19507 bool Diagnose =
true) {
19508 QualType OMPDependT = Stack->getOMPDependT();
19509 if (!OMPDependT.
isNull())
19515 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
19518 Stack->setOMPDependT(PT.
get());
19539 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19544 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19554struct DoacrossDataInfoTy {
19560 llvm::APSInt TotalDepCount;
19563static DoacrossDataInfoTy
19570 llvm::APSInt DepCounter(32);
19571 llvm::APSInt TotalDepCount(32);
19573 if (
const Expr *OrderedCountExpr =
19574 Stack->getParentOrderedRegionParam().first) {
19575 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
19576 TotalDepCount.setIsUnsigned(
true);
19579 for (
Expr *RefExpr : VarList) {
19580 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
19581 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19583 Vars.push_back(RefExpr);
19590 if (Stack->getParentOrderedRegionParam().first &&
19591 DepCounter >= TotalDepCount) {
19592 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19606 Vars.push_back(RefExpr);
19612 Expr *LHS = SimpleExpr;
19613 Expr *RHS =
nullptr;
19614 if (
auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19616 OOLoc = BO->getOperatorLoc();
19619 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19620 OOK = OCE->getOperator();
19621 OOLoc = OCE->getOperatorLoc();
19624 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19625 OOK = MCE->getMethodDecl()
19628 .getCXXOverloadedOperator();
19629 OOLoc = MCE->getCallee()->getExprLoc();
19638 Vars.push_back(RefExpr);
19644 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
19645 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19651 RHS, OMPC_depend,
false);
19656 Stack->getParentOrderedRegionParam().first &&
19657 DepCounter != Stack->isParentLoopControlVariable(
D).first) {
19659 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19661 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19664 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19668 OpsOffs.emplace_back(RHS, OOK);
19670 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19673 TotalDepCount > VarList.size() &&
19674 Stack->getParentOrderedRegionParam().first &&
19675 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19676 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19677 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19679 return {Vars, OpsOffs, TotalDepCount};
19688 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
19689 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19690 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19691 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19694 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
19695 DepKind == OMPC_DEPEND_mutexinoutset) {
19696 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19699 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
19700 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19702 DepKind == OMPC_DEPEND_sink ||
19704 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19705 DepKind == OMPC_DEPEND_depobj))) {
19707 OMPC_DEPEND_outallmemory,
19708 OMPC_DEPEND_inoutallmemory};
19710 DSAStack->getCurrentDirective() == OMPD_depobj)
19711 Except.push_back(OMPC_DEPEND_depobj);
19713 Except.push_back(OMPC_DEPEND_inoutset);
19715 ?
"depend modifier(iterator) or "
19717 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19721 << getOpenMPClauseName(OMPC_depend);
19725 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
19727 diag::err_omp_depend_sink_source_with_modifier);
19732 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
19736 llvm::APSInt TotalDepCount(32);
19738 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
19741 Vars = VarOffset.Vars;
19742 OpsOffs = VarOffset.OpsOffs;
19743 TotalDepCount = VarOffset.TotalDepCount;
19745 for (
Expr *RefExpr : VarList) {
19746 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
19747 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19749 Vars.push_back(RefExpr);
19755 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
19756 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
19757 if (OMPDependTFound)
19759 DepKind == OMPC_DEPEND_depobj);
19760 if (DepKind == OMPC_DEPEND_depobj) {
19764 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19765 !RefExpr->isInstantiationDependent() &&
19766 !RefExpr->containsUnexpandedParameterPack() &&
19767 (OMPDependTFound &&
19769 DSAStack->getOMPDependT(), RefExpr->getType()))) {
19770 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19771 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
19774 if (!RefExpr->isLValue()) {
19775 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19776 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
19783 QualType ExprTy = RefExpr->getType().getNonReferenceType();
19784 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
19791 ExprTy = ATy->getElementType();
19797 const Expr *Length = OASE->getLength();
19799 if (Length && !Length->isValueDependent() &&
19801 Result.Val.getInt().isZero()) {
19803 diag::err_omp_depend_zero_length_array_section_not_allowed)
19813 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19814 !RefExpr->isInstantiationDependent() &&
19815 !RefExpr->containsUnexpandedParameterPack() &&
19816 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
19817 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
19819 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19822 << RefExpr->getSourceRange();
19826 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
19827 if (ASE && !ASE->getBase()->isTypeDependent() &&
19830 .getNonReferenceType()
19831 ->isPointerType() &&
19832 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
19833 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19836 << RefExpr->getSourceRange();
19844 RefExpr->IgnoreParenImpCasts());
19846 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
19847 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
19848 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19851 << RefExpr->getSourceRange();
19856 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19860 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
19861 DepKind != OMPC_DEPEND_outallmemory &&
19862 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
19867 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
19868 TotalDepCount.getZExtValue());
19869 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
19870 DSAStack->isParentOrderedRegion())
19871 DSAStack->addDoacrossDependClause(
C, OpsOffs);
19880 "Unexpected device modifier in OpenMP < 50.");
19882 bool ErrorFound =
false;
19884 std::string Values =
19886 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
19887 << Values << getOpenMPClauseName(OMPC_device);
19892 Stmt *HelperValStmt =
nullptr;
19905 if (Modifier == OMPC_DEVICE_ancestor) {
19909 diag::err_omp_device_ancestor_without_requires_reverse_offload);
19917 if (CaptureRegion != OMPD_unknown &&
19920 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19921 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
19926 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
19927 LParenLoc, ModifierLoc, EndLoc);
19932 bool FullCheck =
true) {
19937 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
19947 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
19952 if (isa<ArraySubscriptExpr>(
E) ||
19953 (OASE && OASE->getColonLocFirst().isInvalid())) {
19954 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
19955 return ATy->getSExtSize() != 1;
19960 assert(OASE &&
"Expecting array section if not an array subscript.");
19961 const Expr *LowerBound = OASE->getLowerBound();
19962 const Expr *Length = OASE->getLength();
19971 llvm::APSInt ConstLowerBound =
Result.Val.getInt();
19972 if (ConstLowerBound.getSExtValue())
19987 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
19995 llvm::APSInt ConstLength =
Result.Val.getInt();
19996 return CATy->getSExtSize() != ConstLength.getSExtValue();
20005 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20009 if (isa<ArraySubscriptExpr>(
E) ||
20010 (OASE && OASE->getColonLocFirst().isInvalid()))
20013 assert(OASE &&
"Expecting array section if not an array subscript.");
20014 const Expr *Length = OASE->getLength();
20020 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20021 return ATy->getSExtSize() != 1;
20031 llvm::APSInt ConstLength =
Result.Val.getInt();
20032 return ConstLength.getSExtValue() != 1;
20071class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
20076 bool IsNonContiguous =
false;
20077 bool NoDiagnose =
false;
20078 const Expr *RelevantExpr =
nullptr;
20079 bool AllowUnitySizeArraySection =
true;
20080 bool AllowWholeSizeArraySection =
true;
20081 bool AllowAnotherPtr =
true;
20085 void emitErrorMsg() {
20087 if (SemaRef.getLangOpts().OpenMP < 50) {
20089 diag::err_omp_expected_named_var_member_or_array_expression)
20092 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20093 << getOpenMPClauseName(CKind) << ERange;
20099 if (!isa<VarDecl>(DRE->
getDecl())) {
20103 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20104 RelevantExpr = DRE;
20106 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
20114 if (isa<CXXThisExpr>(BaseE)) {
20115 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20124 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20140 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20160 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20164 return RelevantExpr || Visit(
E);
20174 AllowUnitySizeArraySection =
false;
20175 AllowWholeSizeArraySection =
false;
20178 Components.emplace_back(ME, FD, IsNonContiguous);
20179 return RelevantExpr || Visit(
E);
20187 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20191 return RelevantExpr || Visit(
E);
20198 AllowWholeSizeArraySection =
false;
20204 !Result.Val.getInt().isZero()) {
20206 diag::err_omp_invalid_map_this_expr);
20208 diag::note_omp_invalid_subscript_on_this_ptr_map);
20210 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20215 Components.emplace_back(AE,
nullptr, IsNonContiguous);
20217 return RelevantExpr || Visit(
E);
20223 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20224 "Array sections cannot be implicitly mapped.");
20238 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20248 if (AllowWholeSizeArraySection) {
20255 if (NotWhole || IsPointer)
20256 AllowWholeSizeArraySection =
false;
20257 }
else if (DKind == OMPD_target_update &&
20258 SemaRef.getLangOpts().OpenMP >= 50) {
20259 if (IsPointer && !AllowAnotherPtr)
20260 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20263 IsNonContiguous =
true;
20264 }
else if (AllowUnitySizeArraySection && NotUnity) {
20270 diag::err_array_section_does_not_specify_contiguous_storage)
20276 AllowAnotherPtr =
false;
20278 if (
const auto *TE = dyn_cast<CXXThisExpr>(
E)) {
20285 diag::err_omp_invalid_map_this_expr);
20287 diag::note_omp_invalid_length_on_this_ptr_mapping);
20291 SemaRef.getASTContext()) &&
20294 diag::err_omp_invalid_map_this_expr);
20296 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20298 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20303 Components.emplace_back(OASE,
nullptr,
false);
20304 return RelevantExpr || Visit(
E);
20310 Components.emplace_back(
E,
nullptr, IsNonContiguous);
20312 return Visit(
Base->IgnoreParenImpCasts());
20316 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
20321 if (!RelevantExpr) {
20323 Components.emplace_back(UO,
nullptr,
false);
20339 Components.emplace_back(BO,
nullptr,
false);
20342 "Either LHS or RHS have base decl inside");
20344 return RelevantExpr || Visit(LE);
20345 return RelevantExpr || Visit(RE);
20348 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20349 RelevantExpr = CTE;
20350 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
20354 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20355 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
20359 Expr *Source =
E->getSourceExpr();
20364 return Visit(Source);
20366 bool VisitStmt(
Stmt *) {
20370 const Expr *getFoundBase()
const {
return RelevantExpr; }
20371 explicit MapBaseChecker(
20375 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20376 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20390 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20394 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20395 (CKind == OMPC_to || CKind == OMPC_from)) {
20396 auto CI = CurComponents.rbegin();
20397 auto CE = CurComponents.rend();
20398 for (; CI != CE; ++CI) {
20400 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20405 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
20409 return Checker.getFoundBase();
20418 bool CurrentRegionOnly,
20429 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
20430 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20431 "Map clause expression with unexpected base!");
20434 bool IsEnclosedByDataEnvironmentExpr =
false;
20435 const Expr *EnclosingExpr =
nullptr;
20437 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20438 VD, CurrentRegionOnly,
20439 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20440 ERange, CKind, &EnclosingExpr,
20444 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
20446 assert(!StackComponents.empty() &&
20447 "Map clause expression with no components!");
20448 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20449 "Map clause expression with unexpected base!");
20453 const Expr *RE = StackComponents.front().getAssociatedExpression();
20459 auto CI = CurComponents.rbegin();
20460 auto CE = CurComponents.rend();
20461 auto SI = StackComponents.rbegin();
20462 auto SE = StackComponents.rend();
20463 for (; CI != CE && SI != SE; ++CI, ++SI) {
20468 if (CurrentRegionOnly &&
20469 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20470 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20471 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20472 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20473 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20474 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20475 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20476 diag::err_omp_multiple_array_items_in_map_clause)
20477 << CI->getAssociatedExpression()->getSourceRange();
20478 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20479 diag::note_used_here)
20480 << SI->getAssociatedExpression()->getSourceRange();
20485 if (CI->getAssociatedExpression()->getStmtClass() !=
20486 SI->getAssociatedExpression()->getStmtClass())
20490 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20496 for (; SI != SE; ++SI) {
20498 if (
const auto *ASE =
20499 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20500 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20501 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
20502 SI->getAssociatedExpression())) {
20503 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20504 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20505 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20506 SI->getAssociatedExpression())) {
20507 Type = OASE->getBase()->getType()->getPointeeType();
20511 SemaRef, SI->getAssociatedExpression(),
Type))
20521 if (CI == CE && SI == SE) {
20522 if (CurrentRegionOnly) {
20523 if (CKind == OMPC_map) {
20524 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20526 assert(CKind == OMPC_to || CKind == OMPC_from);
20527 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20536 IsEnclosedByDataEnvironmentExpr =
true;
20541 std::prev(CI)->getAssociatedDeclaration()->getType();
20543 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20562 if (CI == CE || SI == SE) {
20565 diag::err_omp_pointer_mapped_along_with_derived_section)
20571 if (CI->getAssociatedExpression()->getStmtClass() !=
20572 SI->getAssociatedExpression()->getStmtClass() ||
20573 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20574 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20575 assert(CI != CE && SI != SE);
20576 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20589 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20590 if (CKind == OMPC_map) {
20591 if (CI != CE || SI != SE) {
20595 CI != CE ? CurComponents.begin() : StackComponents.begin();
20596 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20598 while (It != End && !It->getAssociatedDeclaration())
20599 std::advance(It, 1);
20600 assert(It != End &&
20601 "Expected at least one component with the declaration.");
20602 if (It !=
Begin && It->getAssociatedDeclaration()
20604 .getCanonicalType()
20605 ->isAnyPointerType()) {
20606 IsEnclosedByDataEnvironmentExpr =
false;
20607 EnclosingExpr =
nullptr;
20611 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20613 assert(CKind == OMPC_to || CKind == OMPC_from);
20614 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20624 if (!CurrentRegionOnly && SI != SE)
20625 EnclosingExpr = RE;
20629 IsEnclosedByDataEnvironmentExpr |=
20630 (!CurrentRegionOnly && CI != CE && SI == SE);
20635 if (CurrentRegionOnly)
20649 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20651 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20667 Expr *UnresolvedMapper) {
20683 while (S && !S->isDeclScope(
D))
20684 S = S->getParent();
20686 S = S->getParent();
20687 Lookups.emplace_back();
20688 Lookups.back().append(Lookup.
begin(), Lookup.
end());
20691 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20695 auto *DMD = cast<OMPDeclareMapperDecl>(
D);
20696 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
20697 Lookups.back().addDecl(DMD);
20705 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
20706 return !D->isInvalidDecl() &&
20707 (D->getType()->isDependentType() ||
20708 D->getType()->isInstantiationDependentType() ||
20709 D->getType()->containsUnexpandedParameterPack());
20720 false, URS.
begin(), URS.
end(),
false);
20727 SemaRef.
Diag(
Loc, diag::err_omp_mapper_wrong_type);
20734 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20744 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20748 !
Type.isMoreQualifiedThan(
D->getType()))
20767 SemaRef.
Diag(
Loc, diag::err_omp_invalid_mapper)
20777struct MappableVarListInfo {
20792 VarComponents.reserve(VarList.size());
20793 VarBaseDeclarations.reserve(VarList.size());
20811 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
20813 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
20814 "Unexpected clause kind with mappable expressions!");
20822 MapperId.
setName(DeclNames.getIdentifier(
20824 MapperId.
setLoc(StartLoc);
20828 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
20829 bool UpdateUMIt =
false;
20830 Expr *UnresolvedMapper =
nullptr;
20832 bool HasHoldModifier =
20833 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
20841 for (
Expr *RE : MVLI.VarList) {
20842 assert(RE &&
"Null expr in omp to/from/map clause");
20846 if (UpdateUMIt && UMIt != UMEnd) {
20850 "Expect the size of UnresolvedMappers to match with that of VarList");
20854 UnresolvedMapper = *UMIt;
20863 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
20867 MVLI.UDMapperList.push_back(ER.
get());
20870 MVLI.ProcessedVarList.push_back(RE);
20879 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
20882 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20895 DSAS->getCurrentDirective(), NoDiagnose);
20899 assert(!CurComponents.empty() &&
20900 "Invalid mappable expression information.");
20902 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
20904 DSAS->addMappedClassesQualTypes(TE->getType());
20907 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
20911 MVLI.UDMapperList.push_back(ER.
get());
20913 MVLI.ProcessedVarList.push_back(RE);
20914 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
20915 MVLI.VarComponents.back().append(CurComponents.begin(),
20916 CurComponents.end());
20917 MVLI.VarBaseDeclarations.push_back(
nullptr);
20924 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
20925 assert(CurDeclaration &&
"Null decl on map clause.");
20928 "Expecting components to have associated only canonical declarations.");
20930 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
20931 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
20933 assert((VD || FD) &&
"Only variables or fields are expected here!");
20940 if (VD && DSAS->isThreadPrivate(VD)) {
20943 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
20944 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
20945 << getOpenMPClauseName(CKind);
20959 true, CurComponents, CKind))
20961 if (CKind == OMPC_map &&
20964 false, CurComponents, CKind))
20971 auto I = llvm::find_if(
20976 assert(I != CurComponents.end() &&
"Null decl on map clause.");
20979 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->
IgnoreParens());
20980 auto *OASE = dyn_cast<ArraySectionExpr>(VE->
IgnoreParens());
20981 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->
IgnoreParens());
20983 Type = ASE->getType().getNonReferenceType();
20988 Type = ATy->getElementType();
20991 Type =
Type.getNonReferenceType();
20992 }
else if (OAShE) {
21006 if (CKind == OMPC_map) {
21013 if (DKind == OMPD_target_enter_data &&
21014 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21016 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21017 << (IsMapTypeImplicit ? 1 : 0)
21019 << getOpenMPDirectiveName(DKind);
21028 if (DKind == OMPD_target_exit_data &&
21029 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21030 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
21031 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21032 << (IsMapTypeImplicit ? 1 : 0)
21034 << getOpenMPDirectiveName(DKind);
21043 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21045 SemaRef.
Diag(StartLoc,
21046 diag::err_omp_invalid_map_type_modifier_for_directive)
21048 OMPC_MAP_MODIFIER_ompx_hold)
21049 << getOpenMPDirectiveName(DKind);
21057 if ((DKind == OMPD_target_data ||
21059 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21060 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21061 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21062 << (IsMapTypeImplicit ? 1 : 0)
21064 << getOpenMPDirectiveName(DKind);
21076 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
21078 DKind == OMPD_target)) {
21079 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21081 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21082 << getOpenMPClauseName(DVar.CKind)
21083 << getOpenMPClauseName(OMPC_map)
21084 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21093 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
21094 Type.getCanonicalType(), UnresolvedMapper);
21097 MVLI.UDMapperList.push_back(ER.
get());
21100 MVLI.ProcessedVarList.push_back(RE);
21104 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21110 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21111 MVLI.VarComponents.back().append(CurComponents.begin(),
21112 CurComponents.end());
21113 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ?
nullptr
21133 BuiltinType::OMPIterator))
21135 diag::err_omp_map_modifier_not_iterator);
21138 unsigned Count = 0;
21139 for (
unsigned I = 0,
E = MapTypeModifiers.size(); I <
E; ++I) {
21141 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21142 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21146 "Modifiers exceed the allowed number of map type modifiers");
21147 Modifiers[Count] = MapTypeModifiers[I];
21148 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21152 MappableVarListInfo MVLI(VarList);
21154 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21155 MapType, Modifiers, IsMapTypeImplicit,
21161 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21162 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21164 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21172 if (ReductionType.
isNull())
21180 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21185 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21189 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21193 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21196 return ReductionType;
21202 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21205 Decls.reserve(ReductionTypes.size());
21214 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21216 bool InCompoundScope =
true;
21217 if (S !=
nullptr) {
21226 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21228 while (Filter.hasNext()) {
21229 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21230 if (InCompoundScope) {
21231 auto I = UsedAsPrevious.find(PrevDecl);
21232 if (I == UsedAsPrevious.end())
21233 UsedAsPrevious[PrevDecl] =
false;
21235 UsedAsPrevious[
D] =
true;
21237 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21238 PrevDecl->getLocation();
21241 if (InCompoundScope) {
21242 for (
const auto &PrevData : UsedAsPrevious) {
21243 if (!PrevData.second) {
21244 PrevDRD = PrevData.first;
21249 }
else if (PrevDeclInScope !=
nullptr) {
21250 auto *PrevDRDInScope = PrevDRD =
21251 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21253 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21254 PrevDRDInScope->getLocation();
21255 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21256 }
while (PrevDRDInScope !=
nullptr);
21258 for (
const auto &TyData : ReductionTypes) {
21259 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21261 if (I != PreviousRedeclTypes.end()) {
21262 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21264 Diag(I->second, diag::note_previous_definition);
21267 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21269 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21271 DRD->setAccess(AS);
21272 Decls.push_back(DRD);
21274 DRD->setInvalidDecl();
21284 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21299 QualType ReductionType = DRD->getType();
21316 if (S !=
nullptr) {
21320 DRD->addDecl(OmpInParm);
21321 DRD->addDecl(OmpOutParm);
21327 DRD->setCombinerData(InE, OutE);
21332 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21339 if (Combiner !=
nullptr)
21340 DRD->setCombiner(Combiner);
21342 DRD->setInvalidDecl();
21347 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21361 QualType ReductionType = DRD->getType();
21378 if (S !=
nullptr) {
21382 DRD->addDecl(OmpPrivParm);
21383 DRD->addDecl(OmpOrigParm);
21389 DRD->setInitializerData(OrigE, PrivE);
21390 return OmpPrivParm;
21395 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21404 }
else if (OmpPrivParm->
hasInit()) {
21405 DRD->setInitializer(OmpPrivParm->
getInit(),
21410 DRD->setInvalidDecl();
21416 for (
Decl *
D : DeclReductions.
get()) {
21425 return DeclReductions;
21432 if (
D.isInvalidType())
21445 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
21448 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
21453 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21470 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21472 bool InCompoundScope =
true;
21473 if (S !=
nullptr) {
21482 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21484 while (Filter.hasNext()) {
21485 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21486 if (InCompoundScope) {
21487 auto I = UsedAsPrevious.find(PrevDecl);
21488 if (I == UsedAsPrevious.end())
21489 UsedAsPrevious[PrevDecl] =
false;
21491 UsedAsPrevious[
D] =
true;
21493 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21494 PrevDecl->getLocation();
21497 if (InCompoundScope) {
21498 for (
const auto &PrevData : UsedAsPrevious) {
21499 if (!PrevData.second) {
21500 PrevDMD = PrevData.first;
21505 }
else if (PrevDeclInScope) {
21506 auto *PrevDMDInScope = PrevDMD =
21507 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
21509 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
21510 PrevDMDInScope->getLocation();
21511 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
21512 }
while (PrevDMDInScope !=
nullptr);
21516 if (I != PreviousRedeclTypes.end()) {
21517 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
21518 << MapperType << Name;
21519 Diag(I->second, diag::note_previous_definition);
21528 ClausesWithImplicit);
21530 MapperType, VN, ClausesWithImplicit,
21536 DMD->setAccess(AS);
21538 DMD->setInvalidDecl();
21540 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21544 DMD->setMapperVarRef(MapperVarRef);
21565 if (
DSAStack->getDeclareMapperVarRef())
21570 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
21572 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
21585 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
21586 return cast<DeclRefExpr>(
DSAStack->getDeclareMapperVarRef())->getDecl();
21593 Expr *ValExpr = NumTeams;
21594 Stmt *HelperValStmt =
nullptr;
21605 if (CaptureRegion != OMPD_unknown &&
21608 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21609 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
21614 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21621 Expr *ValExpr = ThreadLimit;
21622 Stmt *HelperValStmt =
nullptr;
21633 if (CaptureRegion != OMPD_unknown &&
21636 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21637 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
21642 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21650 Stmt *HelperValStmt =
nullptr;
21656 ValExpr,
SemaRef, OMPC_priority,
21658 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
21662 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21670 "Unexpected grainsize modifier in OpenMP < 51.");
21675 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21676 << Values << getOpenMPClauseName(OMPC_grainsize);
21680 Expr *ValExpr = Grainsize;
21681 Stmt *HelperValStmt =
nullptr;
21691 &CaptureRegion, &HelperValStmt))
21696 StartLoc, LParenLoc, ModifierLoc, EndLoc);
21704 "Unexpected num_tasks modifier in OpenMP < 51.");
21709 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21710 << Values << getOpenMPClauseName(OMPC_num_tasks);
21714 Expr *ValExpr = NumTasks;
21715 Stmt *HelperValStmt =
nullptr;
21722 ValExpr,
SemaRef, OMPC_num_tasks,
21724 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
21729 StartLoc, LParenLoc, ModifierLoc, EndLoc);
21749 DSAStackTy *Stack) {
21750 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
21751 if (!OMPEventHandleT.
isNull())
21756 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
21759 Stack->setOMPEventHandleT(PT.
get());
21780 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
21790 <<
"omp_event_handle_t" << 1 << VD->
getType()
21797 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
21798 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
21801 << getOpenMPClauseName(DVar.CKind)
21802 << getOpenMPClauseName(OMPC_firstprivate);
21817 std::string Values;
21821 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21822 << Values << getOpenMPClauseName(OMPC_dist_schedule);
21825 Expr *ValExpr = ChunkSize;
21826 Stmt *HelperValStmt =
nullptr;
21837 ValExpr = Val.
get();
21842 if (std::optional<llvm::APSInt>
Result =
21844 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
21845 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
21850 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
21854 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21855 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
21863 Kind, ValExpr, HelperValStmt);
21871 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
21872 Kind != OMPC_DEFAULTMAP_scalar) {
21876 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
21878 OMPC_DEFAULTMAP_MODIFIER_tofrom);
21882 OMPC_DEFAULTMAP_scalar);
21886 Diag(
Loc, diag::err_omp_unexpected_clause_value)
21887 <<
Value << getOpenMPClauseName(OMPC_defaultmap);
21894 if (!isDefaultmapKind || !isDefaultmapModifier) {
21895 StringRef KindValue =
"'scalar', 'aggregate', 'pointer'";
21897 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
21898 "'firstprivate', 'none', 'default'";
21899 if (!isDefaultmapKind && isDefaultmapModifier) {
21900 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21901 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
21902 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
21903 Diag(MLoc, diag::err_omp_unexpected_clause_value)
21904 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
21906 Diag(MLoc, diag::err_omp_unexpected_clause_value)
21907 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
21908 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21909 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
21912 StringRef ModifierValue =
21913 "'alloc', 'from', 'to', 'tofrom', "
21914 "'firstprivate', 'none', 'default', 'present'";
21915 if (!isDefaultmapKind && isDefaultmapModifier) {
21916 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21917 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
21918 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
21919 Diag(MLoc, diag::err_omp_unexpected_clause_value)
21920 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
21922 Diag(MLoc, diag::err_omp_unexpected_clause_value)
21923 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
21924 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21925 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
21934 if (
DSAStack->checkDefaultmapCategory(Kind)) {
21935 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
21941 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
21942 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
21943 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
21945 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
21958 !isa<CXXRecordDecl>(CurLexicalContext) &&
21959 !isa<ClassTemplateDecl>(CurLexicalContext) &&
21960 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
21961 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
21962 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
21968 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
21970 DeclareTargetNesting.push_back(DTCI);
21976 assert(!DeclareTargetNesting.empty() &&
21977 "check isInOpenMPDeclareTargetContext() first!");
21978 return DeclareTargetNesting.pop_back_val();
21988 if (DeclareTargetNesting.empty())
21991 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
21992 << getOpenMPDirectiveName(DTCI.
Kind);
22007 VarOrFuncDeclFilterCCC CCC(
SemaRef);
22012 PDiag(diag::err_undeclared_var_use_suggest)
22018 Diag(
Id.getLoc(), diag::err_undeclared_var_use) <<
Id.getName();
22023 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22024 !isa<FunctionTemplateDecl>(ND)) {
22025 Diag(
Id.getLoc(), diag::err_omp_invalid_target_decl) <<
Id.getName();
22034 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22035 isa<FunctionTemplateDecl>(ND)) &&
22036 "Expected variable, function or function template.");
22038 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
22040 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22041 !VD->isStaticDataMember()) {
22042 Diag(
Loc, diag::err_omp_declare_target_has_local_vars)
22051 Diag(
Loc, diag::warn_omp_declare_target_after_first_use);
22055 Diag(
Loc, diag::warn_hip_omp_target_directives);
22058 const unsigned Level = -1;
22060 auto *VD = cast<ValueDecl>(ND);
22061 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22062 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22063 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
22064 (*ActiveAttr)->getLevel() == Level) {
22065 Diag(
Loc, diag::err_omp_device_type_mismatch)
22066 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
22067 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22068 (*ActiveAttr)->getDevType());
22071 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22072 (*ActiveAttr)->getLevel() == Level) {
22073 Diag(
Loc, diag::err_omp_declare_target_to_and_link) << ND;
22077 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22080 Expr *IndirectE =
nullptr;
22081 bool IsIndirect =
false;
22087 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22092 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22094 if (
auto *VD = dyn_cast<VarDecl>(ND);
22096 VD->hasGlobalStorage())
22102 if (!
D || !isa<VarDecl>(
D))
22104 auto *VD = cast<VarDecl>(
D);
22105 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
22106 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22107 if (SemaRef.
LangOpts.OpenMP >= 50 &&
22110 VD->hasGlobalStorage()) {
22111 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22112 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22119 diag::err_omp_lambda_capture_in_declare_target_not_to);
22120 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
22127 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
22128 SemaRef.
Diag(SL, diag::note_used_here) << SR;
22132 Sema &SemaRef, DSAStackTy *Stack,
22134 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22145 if (
auto *VD = dyn_cast<VarDecl>(
D)) {
22147 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22148 !VD->isStaticDataMember())
22152 if (
DSAStack->isThreadPrivate(VD)) {
22153 Diag(SL, diag::err_omp_threadprivate_in_target);
22158 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(
D))
22159 D = FTD->getTemplatedDecl();
22160 if (
auto *FD = dyn_cast<FunctionDecl>(
D)) {
22161 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22162 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22163 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22164 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22169 if (
auto *VD = dyn_cast<ValueDecl>(
D)) {
22177 if (isa<VarDecl>(
D) || isa<FunctionDecl>(
D) ||
22178 isa<FunctionTemplateDecl>(
D)) {
22179 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22180 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22181 unsigned Level = DeclareTargetNesting.size();
22182 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22185 Expr *IndirectE =
nullptr;
22186 bool IsIndirect =
false;
22192 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22194 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22195 : OMPDeclareTargetDeclAttr::MT_To,
22196 DTCI.
DT, IndirectE, IsIndirect, Level,
22200 ML->DeclarationMarkedOpenMPDeclareTarget(
D, A);
22220 if (
auto *VD = dyn_cast<VarDecl>(
Node->getDecl())) {
22222 DeclVector.push_back(VD);
22227 for (
auto *Child : Ex->
children()) {
22236 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
22237 DeclVector.push_back(cast<VarDecl>(TD));
22238 while (!DeclVector.empty()) {
22239 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22240 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
22254 if (isa<VarDecl>(TargetDecl))
22269 unsigned Count = 0;
22270 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22272 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22273 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22277 "Modifiers exceed the allowed number of motion modifiers");
22278 Modifiers[Count] = MotionModifiers[I];
22279 ModifiersLoc[Count] = MotionModifiersLoc[I];
22283 MappableVarListInfo MVLI(VarList);
22285 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22286 if (MVLI.ProcessedVarList.empty())
22290 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22291 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22306 unsigned Count = 0;
22307 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22309 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22310 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22314 "Modifiers exceed the allowed number of motion modifiers");
22315 Modifiers[Count] = MotionModifiers[I];
22316 ModifiersLoc[Count] = MotionModifiersLoc[I];
22320 MappableVarListInfo MVLI(VarList);
22322 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22323 if (MVLI.ProcessedVarList.empty())
22327 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22328 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22335 MappableVarListInfo MVLI(VarList);
22339 for (
Expr *RefExpr : VarList) {
22340 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
22343 Expr *SimpleRefExpr = RefExpr;
22347 MVLI.ProcessedVarList.push_back(RefExpr);
22348 PrivateCopies.push_back(
nullptr);
22349 Inits.push_back(
nullptr);
22356 Type =
Type.getNonReferenceType().getUnqualifiedType();
22358 auto *VD = dyn_cast<VarDecl>(
D);
22362 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22363 << 0 << RefExpr->getSourceRange();
22371 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
22372 if (VDPrivate->isInvalidDecl())
22377 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22393 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22394 PrivateCopies.push_back(VDPrivateRefExpr);
22395 Inits.push_back(VDInitRefExpr);
22400 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22404 MVLI.VarBaseDeclarations.push_back(
D);
22405 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22406 MVLI.VarComponents.back().emplace_back(SimpleRefExpr,
D,
22410 if (MVLI.ProcessedVarList.empty())
22414 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22415 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22421 MappableVarListInfo MVLI(VarList);
22423 for (
Expr *RefExpr : VarList) {
22424 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
22427 Expr *SimpleRefExpr = RefExpr;
22432 MVLI.ProcessedVarList.push_back(RefExpr);
22437 auto *VD = dyn_cast<VarDecl>(
D);
22444 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22449 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22453 MVLI.VarBaseDeclarations.push_back(
D);
22454 MVLI.VarComponents.emplace_back();
22455 Expr *Component = SimpleRefExpr;
22456 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22457 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22460 MVLI.VarComponents.back().emplace_back(Component,
D,
22464 if (MVLI.ProcessedVarList.empty())
22468 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22469 MVLI.VarComponents);
22475 MappableVarListInfo MVLI(VarList);
22476 for (
Expr *RefExpr : VarList) {
22477 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
22480 Expr *SimpleRefExpr = RefExpr;
22484 MVLI.ProcessedVarList.push_back(RefExpr);
22494 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22495 << 0 << RefExpr->getSourceRange();
22501 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
22503 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22504 << getOpenMPClauseName(DVar.CKind)
22505 << getOpenMPClauseName(OMPC_is_device_ptr)
22506 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
22511 const Expr *ConflictExpr;
22512 if (
DSAStack->checkMappableExprComponentListsForDecl(
22517 ConflictExpr = R.front().getAssociatedExpression();
22520 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22529 SimpleRefExpr,
D,
false);
22530 DSAStack->addMappableExpressionComponents(
22531 D, MC, OMPC_is_device_ptr);
22534 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
22539 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22540 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22541 "Unexpected device pointer expression!");
22542 MVLI.VarBaseDeclarations.push_back(
22543 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
22544 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22545 MVLI.VarComponents.back().push_back(MC);
22548 if (MVLI.ProcessedVarList.empty())
22552 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22553 MVLI.VarComponents);
22559 MappableVarListInfo MVLI(VarList);
22560 for (
Expr *RefExpr : VarList) {
22561 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
22564 Expr *SimpleRefExpr = RefExpr;
22569 MVLI.ProcessedVarList.push_back(RefExpr);
22577 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
22579 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22580 << getOpenMPClauseName(DVar.CKind)
22581 << getOpenMPClauseName(OMPC_has_device_addr)
22582 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
22587 const Expr *ConflictExpr;
22588 if (
DSAStack->checkMappableExprComponentListsForDecl(
22593 ConflictExpr = R.front().getAssociatedExpression();
22596 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22604 Expr *Component = SimpleRefExpr;
22605 auto *VD = dyn_cast<VarDecl>(
D);
22606 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22607 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22611 Component,
D,
false);
22612 DSAStack->addMappableExpressionComponents(
22613 D, MC, OMPC_has_device_addr);
22619 assert(Ref &&
"has_device_addr capture failed");
22620 MVLI.ProcessedVarList.push_back(Ref);
22622 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
22627 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22628 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22629 "Unexpected device pointer expression!");
22630 MVLI.VarBaseDeclarations.push_back(
22631 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
22632 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22633 MVLI.VarComponents.back().push_back(MC);
22636 if (MVLI.ProcessedVarList.empty())
22640 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22641 MVLI.VarComponents);
22657 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
22662 Allocator = AllocatorRes.
get();
22675 for (
Expr *RefExpr : VarList) {
22676 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
22679 Expr *SimpleRefExpr = RefExpr;
22683 Vars.push_back(RefExpr);
22689 auto *VD = dyn_cast<VarDecl>(
D);
22694 ? RefExpr->IgnoreParens()
22702 DSAStack->addInnerAllocatorExpr(Allocator);
22704 Allocator, ColonLoc, EndLoc, Vars);
22712 for (
Expr *RefExpr : VarList) {
22713 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
22716 Expr *SimpleRefExpr = RefExpr;
22720 Vars.push_back(RefExpr);
22727 if (
const Expr *PrevRef =
22728 DSAStack->addUniqueNontemporal(
D, SimpleRefExpr)) {
22729 Diag(ELoc, diag::err_omp_used_in_clause_twice)
22730 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
22731 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
22732 << getOpenMPClauseName(OMPC_nontemporal);
22736 Vars.push_back(RefExpr);
22764 for (
Expr *RefExpr : VarList) {
22765 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
22768 Expr *SimpleRefExpr = RefExpr;
22773 Vars.push_back(RefExpr);
22778 const DSAStackTy::DSAVarData DVar =
22784 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
22785 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
22786 << RefExpr->getSourceRange();
22788 if (
DSAStack->getParentDirective() != OMPD_unknown)
22789 DSAStack->markDeclAsUsedInScanDirective(
D);
22790 Vars.push_back(RefExpr);
22805 for (
Expr *RefExpr : VarList) {
22806 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
22809 Expr *SimpleRefExpr = RefExpr;
22814 Vars.push_back(RefExpr);
22820 DSAStackTy::DSAVarData DVar;
22821 if (ParentDirective != OMPD_unknown)
22827 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
22828 DVar.Modifier != OMPC_REDUCTION_inscan) {
22829 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
22830 << RefExpr->getSourceRange();
22832 DSAStack->markDeclAsUsedInScanDirective(
D);
22834 Vars.push_back(RefExpr);
22846 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
22847 if (!OMPAlloctraitT.
isNull())
22852 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
22855 Stack->setOMPAlloctraitT(PT.
get());
22875 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
22876 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
22877 StringRef Allocator =
22878 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
22886 Expr *AllocatorExpr =
nullptr;
22888 if (
D.Allocator->isTypeDependent()) {
22889 AllocatorExpr =
D.Allocator;
22893 AllocatorExpr =
D.Allocator->IgnoreParenImpCasts();
22894 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
22895 bool IsPredefinedAllocator =
false;
22897 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
22899 IsPredefinedAllocator =
22901 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
22905 bool IsTypeCompatible = IsPredefinedAllocator;
22906 IsTypeCompatible = IsTypeCompatible ||
22908 OMPAllocatorHandleT);
22910 IsTypeCompatible ||
22912 bool IsNonConstantLValue =
22914 if (!DRE || !IsTypeCompatible ||
22915 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
22916 Diag(
D.Allocator->getExprLoc(), diag::err_omp_var_expected)
22917 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
22924 if (IsPredefinedAllocator &&
D.AllocatorTraits) {
22925 Diag(
D.AllocatorTraits->getExprLoc(),
22926 diag::err_omp_predefined_allocator_with_traits)
22928 Diag(
D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
22929 << cast<NamedDecl>(DRE->
getDecl())->getName()
22936 if (!IsPredefinedAllocator && !
D.AllocatorTraits) {
22937 Diag(
D.Allocator->getExprLoc(),
22938 diag::err_omp_nonpredefined_allocator_without_traits);
22942 if (!
D.AllocatorTraits)
22946 IsPredefinedAllocator
22947 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
22948 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
22950 Expr *AllocatorTraitsExpr =
nullptr;
22951 if (
D.AllocatorTraits) {
22952 if (
D.AllocatorTraits->isTypeDependent()) {
22953 AllocatorTraitsExpr =
D.AllocatorTraits;
22959 AllocatorTraitsExpr =
D.AllocatorTraits->IgnoreParenImpCasts();
22964 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
22965 TraitTy = ConstArrayTy->getElementType();
22971 Diag(
D.AllocatorTraits->getExprLoc(),
22972 diag::err_omp_expected_array_alloctraits)
22973 << AllocatorTraitsExpr->
getType();
22978 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
22981 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
22998 for (
Expr *RefExpr : Locators) {
22999 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
23000 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23002 Vars.push_back(RefExpr);
23010 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23011 << 1 << 0 << RefExpr->getSourceRange();
23020 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23021 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23022 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23023 << 1 << 0 << RefExpr->getSourceRange();
23026 Vars.push_back(SimpleExpr);
23030 ColonLoc, EndLoc, Modifier, Vars);
23039 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23042 << getOpenMPClauseName(OMPC_bind);
23047 LParenLoc, EndLoc);
23054 Expr *ValExpr = Size;
23055 Stmt *HelperValStmt =
nullptr;
23066 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
23067 if (CaptureRegion != OMPD_unknown &&
23070 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23071 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23076 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23084 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
23085 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23086 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23087 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
23088 DepType != OMPC_DOACROSS_source) {
23089 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23090 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23096 llvm::APSInt TotalDepCount(32);
23099 DepType == OMPC_DOACROSS_source ||
23100 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23101 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23103 Vars = VarOffset.Vars;
23104 OpsOffs = VarOffset.OpsOffs;
23105 TotalDepCount = VarOffset.TotalDepCount;
23107 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23108 TotalDepCount.getZExtValue());
23109 if (
DSAStack->isParentOrderedRegion())
23110 DSAStack->addDoacrossDependClause(
C, OpsOffs);
23132 if (
Base->hasPlaceholderType() &&
23133 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23146 LowerBound =
Result.get();
23148 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23168 if (
Base->isTypeDependent() ||
23171 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23175 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23187 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23188 <<
Base->getSourceRange());
23194 if (Res.isInvalid())
23196 diag::err_omp_typecheck_section_not_integer)
23198 LowerBound = Res.get();
23208 if (Res.isInvalid())
23210 diag::err_omp_typecheck_section_not_integer)
23211 << 1 << Length->getSourceRange());
23212 Length = Res.get();
23214 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23215 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23216 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23217 << 1 << Length->getSourceRange();
23224 diag::err_omp_typecheck_section_not_integer)
23226 Stride = Res.
get();
23239 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
23240 << ResultTy <<
Base->getSourceRange();
23245 diag::err_omp_section_incomplete_type,
Base))
23253 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
23254 if (LowerBoundValue.isNegative()) {
23256 diag::err_omp_section_not_subset_of_array)
23265 if (Length->EvaluateAsInt(
Result, Context)) {
23268 llvm::APSInt LengthValue =
Result.Val.getInt();
23269 if (LengthValue.isNegative()) {
23270 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23271 <<
toString(LengthValue, 10,
true)
23272 << Length->getSourceRange();
23276 }
else if (ColonLocFirst.
isValid() &&
23282 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23292 llvm::APSInt StrideValue =
Result.Val.getInt();
23293 if (!StrideValue.isStrictlyPositive()) {
23294 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
23295 <<
toString(StrideValue, 10,
true)
23302 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23310 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23317 if (
Base->hasPlaceholderType()) {
23331 LParenLoc, RParenLoc, Dims, Brackets);
23333 (!
Base->isTypeDependent() &&
23336 diag::err_omp_non_pointer_type_array_shaping_base)
23337 <<
Base->getSourceRange());
23340 bool ErrorFound =
false;
23341 for (
Expr *Dim : Dims) {
23342 if (Dim->hasPlaceholderType()) {
23344 if (
Result.isInvalid()) {
23349 if (
Result.isInvalid()) {
23355 if (!Dim->isTypeDependent()) {
23358 if (
Result.isInvalid()) {
23360 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23361 << Dim->getSourceRange();
23366 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23371 if (!
Value.isStrictlyPositive()) {
23372 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23374 << Dim->getSourceRange();
23380 NewDims.push_back(Dim);
23385 LParenLoc, RParenLoc, NewDims, Brackets);
23395 bool IsCorrect =
true;
23400 if (!
D.Type.getAsOpaquePtr()) {
23404 DeclTy = Context.
IntTy;
23405 StartLoc =
D.DeclIdentLoc;
23411 bool IsDeclTyDependent = DeclTy->isDependentType() ||
23412 DeclTy->containsUnexpandedParameterPack() ||
23413 DeclTy->isInstantiationDependentType();
23414 if (!IsDeclTyDependent) {
23415 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23418 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23423 if (DeclTy.isConstant(Context)) {
23426 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23434 assert(
D.DeclIdent &&
"Identifier expected.");
23439 D.DeclIdent, DeclTy, TInfo,
SC_None);
23445 RedeclarationKind::ForVisibleRedeclaration);
23467 if (!IsDeclTyDependent &&
Begin && !
Begin->isTypeDependent()) {
23472 Expr *End =
D.Range.End;
23473 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
23476 End = EndRes.
get();
23478 Expr *Step =
D.Range.Step;
23481 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
23486 std::optional<llvm::APSInt>
Result =
23492 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
23498 if (!
Begin || !End || !IsCorrect) {
23514 if (
Decl *ID =
D.IteratorDecl)
23515 ID->setInvalidDecl();
23527 D.Range.End,
D.Range.Begin);
23533 if (
D.Range.Step) {
23544 D.AssignmentLoc, BO_Sub, Res.
get(),
23561 D.AssignmentLoc, BO_Sub,
D.Range.Begin,
D.Range.End);
23575 D.AssignmentLoc, BO_Sub, Res1.
get(),
23590 D.AssignmentLoc, BO_GT,
D.Range.Step,
23615 CounterVD->setImplicit();
23622 if (
D.Range.Step) {
23624 D.AssignmentLoc, BO_Mul,
23634 D.Range.Begin, UpdateRes.
get());
23641 cast<VarDecl>(
D.IteratorDecl)->getType(),
23644 VDRes.
get(), UpdateRes.
get());
23656 D.AssignmentLoc, UO_PreInc, RefRes.
get());
23657 if (!CounterUpdateRes.
isUsable()) {
23663 if (!CounterUpdateRes.
isUsable()) {
23674 Helpers.assign(ID.size(), {});
23679 if (
Decl *ID =
D.IteratorDecl)
23680 ID->setInvalidDecl();
23685 LLoc, RLoc, ID, Helpers);
23690 StringRef AssumptionStr) {
23691 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
23694 unsigned BestEditDistance = 3;
23695 StringRef Suggestion;
23696 for (
const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
23697 unsigned EditDistance =
23698 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
23699 if (EditDistance < BestEditDistance) {
23700 Suggestion = KnownAssumptionIt.getKey();
23701 BestEditDistance = EditDistance;
23705 if (!Suggestion.empty())
23706 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
23707 << AssumptionStr << Suggestion;
23709 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown)
23726 :
SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
enum clang::sema::@1651::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 ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static 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 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 SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude=std::nullopt)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static 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 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)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static VarDecl * buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, StringRef Name, const AttrVec *Attrs=nullptr, DeclRefExpr *OrigRef=nullptr)
Build a variable declaration for OpenMP loop iteration variable.
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers=std::nullopt, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propageted from the selected loop.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
static QualType getPointeeType(const MemRegion *R)
Allows QualTypes to be sorted and hence used in maps and sets.
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const
Return a non-unique reference to the type for a variable array of the specified element type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
CanQualType OMPArrayShapingTy
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
void Deallocate(void *Ptr) const
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
CanQualType OMPIteratorTy
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType ArraySectionTy
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType BoundMemberTy
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified=false)
Compatibility predicates used to check assignment expressions.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Expr * getBase()
Get base of the array section.
Expr * getLength()
Get length of array section.
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Expr * getLowerBound()
Get lower bound of array section.
SourceLocation getColonLocFirst() const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
Represents an attribute applied to a statement.
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
A builtin binary operation expression such as "x + y" or "x <= y".
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
static Opcode getOpForCompoundAssignment(Opcode Opc)
bool isRelationalOp() const
SourceLocation getOperatorLoc() const
SourceLocation getExprLoc() const
static Opcode reverseComparisonOp(Opcode Opc)
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a C++ constructor within a class.
Represents a C++ conversion function within a class.
A call to an overloaded operator written using operator syntax.
Represents a C++ struct/union/class.
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
bool hasDefinition() const
Represents a C++ nested-name-specifier or a global scope specifier.
bool isValid() const
A scope specifier is present, and it refers to a real scope.
SourceLocation getBeginLoc() const
bool isSet() const
Deprecated.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Represents the this expression in C++.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
SourceLocation getBeginLoc() const LLVM_READONLY
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
QualType withConst() const
Retrieves a version of this type with const applied.
A wrapper class around a pointer that always points to its canonical declaration.
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getNumParams() const
void setNothrow(bool Nothrow=true)
ImplicitParamDecl * getParam(unsigned i) const
Describes the capture of either a variable, or 'this', or variable-length array type.
This captures a statement into a function.
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
SourceRange getSourceRange() const LLVM_READONLY
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
SourceLocation getBeginLoc() const LLVM_READONLY
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Declaration of a class template.
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
ConditionalOperator - The ?: ternary operator.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
bool isFileContext() const
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
A reference to a declared variable, function, enum, etc.
SourceLocation getBeginLoc() const LLVM_READONLY
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
SourceLocation getEndLoc() const LLVM_READONLY
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getEndLoc() const
const DeclGroupRef getDeclGroup() const
const Decl * getSingleDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
bool isReferenced() const
Whether any declaration of this entity was referenced.
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
bool isInvalidDecl() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
void setAccess(AccessSpecifier AS)
SourceLocation getLocation() const
void setImplicit(bool I=true)
void setReferenced(bool R=true)
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
SourceLocation getBeginLoc() const LLVM_READONLY
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
void setLexicalDeclContext(DeclContext *DC)
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
RAII object that enters a new expression evaluation context.
The return type of classify().
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
ArrayRef< ParmVarDecl * > parameters() const
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Represents a prototype with parameter type info, e.g.
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A class for iterating through a result set and possibly filtering out results.
Represents the results of name lookup.
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
DeclClass * getAsSingle() const
bool empty() const
Return true if no decls were found.
Filter makeFilter()
Create a filter for this result set.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
A C++ nested-name-specifier augmented with source location information.
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the '#pragma omp ...' directive.
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
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 'shedule', 'firstprivate' etc.
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 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 'if' clause in the '#pragma omp ...' directive.
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the '#pragma omp ...' directives.
Expr * getStep()
Returns linear step.
void setUpdates(ArrayRef< Expr * > UL)
Sets the list of update expressions for linear variables.
privates_range privates()
void setFinals(ArrayRef< Expr * > FL)
Sets the list of final update expressions for linear variables.
void setUsedExprs(ArrayRef< Expr * > UE)
Sets the list of used expressions for the linear clause.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
Expr * getCalcStep()
Returns expression to calculate linear step.
OpenMPLinearClauseKind getModifier() const
Return modifier.
The base class for all loop-based directives, including loop transformation directives.
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt)
Creates directive.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'mergeable' clause in the '#pragma omp ...' directive.
This represents 'message' clause in the '#pragma omp error' directive.
Expr * getMessageString() const
Returns message string of the clause.
This represents 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the '#pragma omp ...' directive.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
This represents 'num_teams' clause in the '#pragma omp ...' directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
This represents 'order' clause in the '#pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the '#pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
static OMPOrderedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This represents 'priority' clause in the '#pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents 'read' clause in the '#pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
This represents '#pragma omp requires...' directive.
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp reverse'.
This represents 'reverse_offload' clause in the '#pragma omp requires' directive.
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
This represents 'schedule' clause in the '#pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
static OMPScopeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
static OMPSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
This represents 'seq_cst' clause in the '#pragma omp atomic' directive.
This represents 'severity' clause in the '#pragma omp error' directive.
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPTaskgroupDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *ReductionRef)
Creates directive.
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'thread_limit' clause in the '#pragma omp ...' directive.
This represents '#pragma omp threadprivate ...' directive.
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threads' clause in the '#pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp tile'.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the '#pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the '#pragma omp requires' directive.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp unroll'.
This represents 'untied' clause in the '#pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
This represents the 'use' clause in '#pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
SourceLocation getLParenLoc() const
Returns the location of '('.
unsigned varlist_size() const
This represents 'weak' clause in the '#pragma omp atomic' directives.
This represents 'write' clause in the '#pragma omp atomic' directive.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the '#pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the '#pragma omp target ...' directive.
Wrapper for void* pointer.
void * getAsOpaquePtr() const
static OpaquePtr make(PtrTy P)
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
ParsedAttr - Represents a syntactic attribute.
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool hasQualifiers() const
Determine whether this type has any qualifiers.
QualType withRestrict() const
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType withConst() const
void addConst()
Add the const type qualifier to this QualType.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
bool isConstant(const ASTContext &Ctx) const
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
const Type * getTypePtrOrNull() const
Represents a struct/union/class.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
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.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'reduction' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the '#pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'from' clause.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'to' clause.
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
OMPClause * ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interchange' after parsing of its clauses and the associated state...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
OMPClause * ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'task_reduction' clause.
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult 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)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
std::pair< StringRef, QualType > CapturedParamNameType
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp tile' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
OMPClause * ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Abstract base class used for diagnosing integer constant expression violations.
Sema - This implements semantic analysis and AST building for C.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false) const
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
@ LookupAnyName
Look up any declaration with any name.
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
PoppedFunctionScopePtr PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP=nullptr, const Decl *D=nullptr, QualType BlockType=QualType())
Pop a function (or block or lambda or captured region) scope from the stack.
bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit=false, bool BuildAndDiagnose=true, const unsigned *const FunctionScopeIndexToStopAt=nullptr, bool ByCopy=false)
Make sure the value of 'this' is actually available in the current context, if it is a potentially ev...
NamedDecl * HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists)
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
FPOptionsOverride CurFPFeatureOverrides()
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt=std::nullopt)
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
void CleanupVarDeclMarking()
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
ASTContext & getASTContext() const
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt)
Try to capture the given variable.
void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var)
Mark a variable referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
void PopExpressionEvaluationContext()
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef< Expr * > Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses)
Find the associated classes and namespaces for argument-dependent lookup for a call with the given se...
void PushFunctionScope()
Enter a new function scope.
const LangOptions & getLangOpts() const
TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext=nullptr, bool EnteringContext=false, const ObjCObjectPointerType *OPT=nullptr, bool RecordFailure=true)
Try to "correct" a typo in the source code by finding visible declarations whose names are similar to...
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)
Checks access for a hierarchy conversion.
void CheckExtraCXXDefaultArguments(Declarator &D)
CheckExtraCXXDefaultArguments - Check for any extra default arguments in the declarator,...
const LangOptions & LangOpts
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
DeclContext * getCurLexicalContext() const
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
sema::FunctionScopeInfo * getCurFunction() const
Expr * BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit)
Build a CXXThisExpr and mark it referenced in the current context.
ExprResult DefaultLvalueConversion(Expr *E)
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
@ TryCapture_ExplicitByVal
bool areMultiversionVariantFunctionsCompatible(const FunctionDecl *OldFD, const FunctionDecl *NewFD, const PartialDiagnostic &NoProtoDiagID, const PartialDiagnosticAt &NoteCausedDiagIDAt, const PartialDiagnosticAt &NoSupportDiagIDAt, const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported, bool ConstexprSupported, bool CLinkageMayDiffer)
Checks if the variant/multiversion functions are compatible.
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
void setFunctionHasBranchProtectedScope()
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
TypeSourceInfo * GetTypeForDeclarator(Declarator &D)
GetTypeForDeclarator - Convert the type for the specified declarator to Type instances.
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace)
Filters out lookup results that don't fall within the given scope as determined by isDeclInScope.
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
sema::FunctionScopeInfo * getEnclosingFunction() const
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
FullExprArg MakeFullExpr(Expr *Arg)
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation 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
bool isTLSSupported() const
Whether the target supports thread-local storage.
bool isVLASupported() const
Whether target supports variable-length arrays.
Represents a declaration of a type.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
bool isArithmeticType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isScalarType() const
bool isVariableArrayType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAnyComplexType() const
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isFunctionProtoType() const
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
bool isFunctionType() const
bool isStructureOrClassType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool isFunctionNoProtoType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent)
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)
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
void setInitStyle(InitializationStyle Style)
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
@ CallInit
Call-style initialization (C++98)
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Directive - Abstract class representing a parsed verify directive.
Retains information about a captured region.
unsigned short OpenMPLevel
unsigned short OpenMPCaptureLevel
Retains information about a function, method, or block that is currently being parsed.
void setHasOMPDeclareReductionCombiner()
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Defines the clang::TargetInfo interface.
bool LE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Expr * AssertSuccess(ExprResult R)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ LCK_This
Capturing the *this object by reference.
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
OpenMPGrainsizeClauseModifier
OpenMPNumTasksClauseModifier
ActionResult< Expr * > ExprResult
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ActionResult< Decl * > DeclResult
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
bool isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a combined construct for which the first construct is a parallel...
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Extra information about a function prototype.
llvm::SmallVector< Expr *, 4 > PreferTypes
Iterator definition representation.
SourceLocation AssignmentLoc
SourceLocation SecondColonLoc
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Expr * Upper
Normalized upper bound.
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
VarDecl * CounterVD
Internal normalized counter.
Expr * ParForInDistCond
'omp parallel for' loop condition used when composed with 'omp distribute' in the same construct and ...
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Expr * LastIteration
Loop last iteration number.
Expr * Cond
Loop condition.
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Expr * IL
IsLastIteration - local flag variable passed to runtime.
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Expr * CalcLastIteration
Calculation of last iteration.
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Expr * ST
Stride - local variable passed to runtime.
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Expr * PreCond
Loop pre-condition.
Stmt * PreInits
Init statement for all captured expressions.
Expr * IterationVarRef
Loop iteration variable.
Expr * NumIterations
Loop number of iterations.
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
void clear(unsigned Size)
Initialize all the fields to null.
Expr * Inc
Loop increment.
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Expr * UB
UpperBound - local variable passed to runtime.
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Expr * LB
LowerBound - local variable passed to runtime.
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Expr * Init
Loop iteration variable init.
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
std::optional< Expr * > Indirect
The directive with indirect clause.
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
SourceLocation Loc
The directive location.
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Data structure for iterator expression.
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Clang specific specialization of the OMPContext to lookup target features.