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) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_present);
812 case OMPC_DEFAULTMAP_scalar:
813 case OMPC_DEFAULTMAP_pointer:
815 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
816 (M == OMPC_DEFAULTMAP_MODIFIER_default);
817 case OMPC_DEFAULTMAP_aggregate:
818 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
822 llvm_unreachable(
"Unexpected OpenMPDefaultmapClauseKind enum");
824 bool mustBeFirstprivateAtLevel(
unsigned Level,
827 getDefaultmapModifierAtLevel(Level, Kind);
828 return mustBeFirstprivateBase(M, Kind);
832 return mustBeFirstprivateBase(M, Kind);
837 const DSAVarData DVar = getTopDSA(
D,
false);
842 void setOrderedRegion(
bool IsOrdered,
const Expr *Param,
845 getTopOfStack().OrderedRegion.emplace(Param, Clause);
847 getTopOfStack().OrderedRegion.reset();
851 bool isOrderedRegion()
const {
852 if (
const SharingMapTy *Top = getTopOfStackOrNull())
853 return Top->OrderedRegion.has_value();
857 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam()
const {
858 if (
const SharingMapTy *Top = getTopOfStackOrNull())
859 if (Top->OrderedRegion)
860 return *Top->OrderedRegion;
861 return std::make_pair(
nullptr,
nullptr);
865 bool isParentOrderedRegion()
const {
866 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
867 return Parent->OrderedRegion.has_value();
871 std::pair<const Expr *, OMPOrderedClause *>
872 getParentOrderedRegionParam()
const {
873 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
874 if (
Parent->OrderedRegion)
875 return *
Parent->OrderedRegion;
876 return std::make_pair(
nullptr,
nullptr);
879 void setRegionHasOrderConcurrent(
bool HasOrderConcurrent) {
880 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
884 bool isParentOrderConcurrent()
const {
885 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
886 return Parent->RegionHasOrderConcurrent;
890 void setNowaitRegion(
bool IsNowait =
true) {
891 getTopOfStack().NowaitRegion = IsNowait;
895 bool isParentNowaitRegion()
const {
896 if (
const SharingMapTy *
Parent = getSecondOnStackOrNull())
897 return Parent->NowaitRegion;
901 void setUntiedRegion(
bool IsUntied =
true) {
902 getTopOfStack().UntiedRegion = IsUntied;
905 bool isUntiedRegion()
const {
906 const SharingMapTy *Top = getTopOfStackOrNull();
907 return Top ? Top->UntiedRegion :
false;
910 void setParentCancelRegion(
bool Cancel =
true) {
911 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
912 Parent->CancelRegion |= Cancel;
915 bool isCancelRegion()
const {
916 const SharingMapTy *Top = getTopOfStackOrNull();
917 return Top ? Top->CancelRegion :
false;
922 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
926 bool doesParentHasScanDirective()
const {
927 const SharingMapTy *Top = getSecondOnStackOrNull();
928 return Top ? Top->PrevScanLocation.isValid() :
false;
932 const SharingMapTy *Top = getSecondOnStackOrNull();
937 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
941 bool doesParentHasOrderedDirective()
const {
942 const SharingMapTy *Top = getSecondOnStackOrNull();
943 return Top ? Top->PrevOrderedLocation.isValid() :
false;
947 const SharingMapTy *Top = getSecondOnStackOrNull();
952 void setAssociatedLoops(
unsigned Val) {
953 getTopOfStack().AssociatedLoops = Val;
955 getTopOfStack().HasMutipleLoops =
true;
958 unsigned getAssociatedLoops()
const {
959 const SharingMapTy *Top = getTopOfStackOrNull();
960 return Top ? Top->AssociatedLoops : 0;
963 bool hasMutipleLoops()
const {
964 const SharingMapTy *Top = getTopOfStackOrNull();
965 return Top ? Top->HasMutipleLoops :
false;
971 if (SharingMapTy *
Parent = getSecondOnStackOrNull())
972 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
975 bool hasInnerTeamsRegion()
const {
976 return getInnerTeamsRegionLoc().
isValid();
980 const SharingMapTy *Top = getTopOfStackOrNull();
984 Scope *getCurScope()
const {
985 const SharingMapTy *Top = getTopOfStackOrNull();
986 return Top ? Top->CurScope :
nullptr;
988 void setContext(
DeclContext *DC) { getTopOfStack().Context = DC; }
990 const SharingMapTy *Top = getTopOfStackOrNull();
996 bool checkMappableExprComponentListsForDecl(
997 const ValueDecl *VD,
bool CurrentRegionOnly,
998 const llvm::function_ref<
1010 if (CurrentRegionOnly)
1013 std::advance(SI, 1);
1015 for (; SI != SE; ++SI) {
1016 auto MI = SI->MappedExprComponents.find(VD);
1017 if (MI != SI->MappedExprComponents.end())
1019 MI->second.Components)
1020 if (Check(L, MI->second.Kind))
1028 bool checkMappableExprComponentListsForDeclAtLevel(
1030 const llvm::function_ref<
1034 if (getStackSize() <= Level)
1037 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1038 auto MI = StackElem.MappedExprComponents.find(VD);
1039 if (MI != StackElem.MappedExprComponents.end())
1041 MI->second.Components)
1042 if (Check(L, MI->second.Kind))
1049 void addMappableExpressionComponents(
1053 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1055 MEC.Components.resize(MEC.Components.size() + 1);
1056 MEC.Components.back().append(Components.begin(), Components.end());
1057 MEC.Kind = WhereFoundClauseKind;
1060 unsigned getNestingLevel()
const {
1061 assert(!isStackEmpty());
1062 return getStackSize() - 1;
1064 void addDoacrossDependClause(
OMPClause *
C,
const OperatorOffsetTy &OpsOffs) {
1065 SharingMapTy *
Parent = getSecondOnStackOrNull();
1067 Parent->DoacrossDepends.try_emplace(
C, OpsOffs);
1069 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1070 getDoacrossDependClauses()
const {
1071 const SharingMapTy &StackElem = getTopOfStack();
1073 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1074 return llvm::make_range(Ref.begin(), Ref.end());
1076 return llvm::make_range(StackElem.DoacrossDepends.end(),
1077 StackElem.DoacrossDepends.end());
1081 void addMappedClassesQualTypes(
QualType QT) {
1082 SharingMapTy &StackElem = getTopOfStack();
1083 StackElem.MappedClassesQualTypes.insert(QT);
1087 bool isClassPreviouslyMapped(
QualType QT)
const {
1088 const SharingMapTy &StackElem = getTopOfStack();
1089 return StackElem.MappedClassesQualTypes.contains(QT);
1093 void addToParentTargetRegionLinkGlobals(
DeclRefExpr *
E) {
1094 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1095 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1096 "Expected declare target link global.");
1097 for (
auto &Elem : *
this) {
1099 Elem.DeclareTargetLinkVarDecls.push_back(
E);
1109 "Expected target executable directive.");
1110 return getTopOfStack().DeclareTargetLinkVarDecls;
1114 void addInnerAllocatorExpr(
Expr *
E) {
1115 getTopOfStack().InnerUsedAllocators.push_back(
E);
1119 return getTopOfStack().InnerUsedAllocators;
1123 void addImplicitTaskFirstprivate(
unsigned Level,
Decl *
D) {
1124 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(
D);
1127 bool isImplicitTaskFirstprivate(
Decl *
D)
const {
1128 return getTopOfStack().ImplicitTaskFirstprivates.contains(
D);
1132 void addUsesAllocatorsDecl(
const Decl *
D, UsesAllocatorsDeclKind Kind) {
1133 getTopOfStack().UsesAllocatorsDecls.try_emplace(
D, Kind);
1137 std::optional<UsesAllocatorsDeclKind>
1138 isUsesAllocatorsDecl(
unsigned Level,
const Decl *
D)
const {
1139 const SharingMapTy &StackElem = getTopOfStack();
1140 auto I = StackElem.UsesAllocatorsDecls.find(
D);
1141 if (I == StackElem.UsesAllocatorsDecls.end())
1142 return std::nullopt;
1143 return I->getSecond();
1145 std::optional<UsesAllocatorsDeclKind>
1146 isUsesAllocatorsDecl(
const Decl *
D)
const {
1147 const SharingMapTy &StackElem = getTopOfStack();
1148 auto I = StackElem.UsesAllocatorsDecls.find(
D);
1149 if (I == StackElem.UsesAllocatorsDecls.end())
1150 return std::nullopt;
1151 return I->getSecond();
1154 void addDeclareMapperVarRef(
Expr *Ref) {
1155 SharingMapTy &StackElem = getTopOfStack();
1156 StackElem.DeclareMapperVar = Ref;
1158 const Expr *getDeclareMapperVarRef()
const {
1159 const SharingMapTy *Top = getTopOfStackOrNull();
1160 return Top ? Top->DeclareMapperVar :
nullptr;
1164 void addIteratorVarDecl(
VarDecl *VD) {
1165 SharingMapTy &StackElem = getTopOfStack();
1169 bool isIteratorVarDecl(
const VarDecl *VD)
const {
1170 const SharingMapTy *Top = getTopOfStackOrNull();
1178 const_iterator I = begin();
1179 const_iterator EndI = end();
1180 size_t StackLevel = getStackSize();
1181 for (; I != EndI; ++I) {
1182 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1186 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1189 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1190 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1195 bool isImplicitDefaultFirstprivateFD(
VarDecl *VD)
const {
1196 const_iterator I = begin();
1197 const_iterator EndI = end();
1198 for (; I != EndI; ++I)
1199 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1203 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1210 iterator I = begin();
1211 const_iterator EndI = end();
1212 size_t StackLevel = getStackSize();
1213 for (; I != EndI; ++I) {
1214 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1215 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1220 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1230 DKind == OMPD_unknown;
1236 if (
const auto *FE = dyn_cast<FullExpr>(
E))
1237 E = FE->getSubExpr();
1239 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
E))
1240 E = MTE->getSubExpr();
1242 while (
const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(
E))
1243 E = Binder->getSubExpr();
1245 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(
E))
1246 E = ICE->getSubExprAsWritten();
1255 if (
const auto *CED = dyn_cast<OMPCapturedExprDecl>(
D))
1256 if (
const auto *ME = dyn_cast<MemberExpr>(
getExprAsWritten(CED->getInit())))
1257 D = ME->getMemberDecl();
1258 const auto *VD = dyn_cast<VarDecl>(
D);
1259 const auto *FD = dyn_cast<FieldDecl>(
D);
1260 if (VD !=
nullptr) {
1276DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &
Iter,
1279 auto *VD = dyn_cast<VarDecl>(
D);
1280 const auto *FD = dyn_cast<FieldDecl>(
D);
1282 if (
Iter == end()) {
1289 DVar.CKind = OMPC_shared;
1296 DVar.CKind = OMPC_shared;
1300 DVar.CKind = OMPC_shared;
1311 DVar.CKind = OMPC_private;
1315 DVar.DKind =
Iter->Directive;
1318 if (
Iter->SharingMap.count(
D)) {
1319 const DSAInfo &
Data =
Iter->SharingMap.lookup(
D);
1320 DVar.RefExpr =
Data.RefExpr.getPointer();
1321 DVar.PrivateCopy =
Data.PrivateCopy;
1322 DVar.CKind =
Data.Attributes;
1323 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1324 DVar.Modifier =
Data.Modifier;
1325 DVar.AppliedToPointee =
Data.AppliedToPointee;
1333 switch (
Iter->DefaultAttr) {
1335 DVar.CKind = OMPC_shared;
1336 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1340 case DSA_firstprivate:
1343 DVar.CKind = OMPC_unknown;
1345 DVar.CKind = OMPC_firstprivate;
1347 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1355 DVar.CKind = OMPC_unknown;
1357 DVar.CKind = OMPC_private;
1359 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1361 case DSA_unspecified:
1366 DVar.ImplicitDSALoc =
Iter->DefaultAttrLoc;
1370 DVar.CKind = OMPC_shared;
1380 DSAVarData DVarTemp;
1381 const_iterator I =
Iter,
E = end();
1389 DVarTemp = getDSA(I,
D);
1390 if (DVarTemp.CKind != OMPC_shared) {
1391 DVar.RefExpr =
nullptr;
1392 DVar.CKind = OMPC_firstprivate;
1395 }
while (I !=
E && !isImplicitTaskingRegion(I->Directive));
1397 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1406 return getDSA(++
Iter,
D);
1410 const Expr *NewDE) {
1411 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1413 SharingMapTy &StackElem = getTopOfStack();
1414 auto It = StackElem.AlignedMap.find(
D);
1415 if (It == StackElem.AlignedMap.end()) {
1416 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1417 StackElem.AlignedMap[
D] = NewDE;
1420 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1425 const Expr *NewDE) {
1426 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1428 SharingMapTy &StackElem = getTopOfStack();
1429 auto It = StackElem.NontemporalMap.find(
D);
1430 if (It == StackElem.NontemporalMap.end()) {
1431 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1432 StackElem.NontemporalMap[
D] = NewDE;
1435 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1440 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1442 SharingMapTy &StackElem = getTopOfStack();
1443 StackElem.LCVMap.try_emplace(
1444 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1447const DSAStackTy::LCDeclInfo
1448DSAStackTy::isLoopControlVariable(
const ValueDecl *
D)
const {
1449 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1451 const SharingMapTy &StackElem = getTopOfStack();
1452 auto It = StackElem.LCVMap.find(
D);
1453 if (It != StackElem.LCVMap.end())
1455 return {0,
nullptr};
1458const DSAStackTy::LCDeclInfo
1459DSAStackTy::isLoopControlVariable(
const ValueDecl *
D,
unsigned Level)
const {
1460 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1462 for (
unsigned I = Level + 1; I > 0; --I) {
1463 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1464 auto It = StackElem.LCVMap.find(
D);
1465 if (It != StackElem.LCVMap.end())
1468 return {0,
nullptr};
1471const DSAStackTy::LCDeclInfo
1472DSAStackTy::isParentLoopControlVariable(
const ValueDecl *
D)
const {
1473 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1474 assert(
Parent &&
"Data-sharing attributes stack is empty");
1476 auto It =
Parent->LCVMap.find(
D);
1477 if (It !=
Parent->LCVMap.end())
1479 return {0,
nullptr};
1482const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1483 const SharingMapTy *
Parent = getSecondOnStackOrNull();
1484 assert(
Parent &&
"Data-sharing attributes stack is empty");
1485 if (
Parent->LCVMap.size() < I)
1487 for (
const auto &Pair :
Parent->LCVMap)
1488 if (Pair.second.first == I)
1495 bool AppliedToPointee) {
1497 if (A == OMPC_threadprivate) {
1498 DSAInfo &
Data = Threadprivates[
D];
1499 Data.Attributes = A;
1500 Data.RefExpr.setPointer(
E);
1501 Data.PrivateCopy =
nullptr;
1502 Data.Modifier = Modifier;
1504 DSAInfo &
Data = getTopOfStack().SharingMap[
D];
1505 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1506 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1507 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1508 (isLoopControlVariable(
D).first && A == OMPC_private));
1509 Data.Modifier = Modifier;
1510 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1511 Data.RefExpr.setInt(
true);
1514 const bool IsLastprivate =
1515 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1516 Data.Attributes = A;
1517 Data.RefExpr.setPointerAndInt(
E, IsLastprivate);
1518 Data.PrivateCopy = PrivateCopy;
1519 Data.AppliedToPointee = AppliedToPointee;
1521 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1522 Data.Modifier = Modifier;
1523 Data.Attributes = A;
1524 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1525 Data.PrivateCopy =
nullptr;
1526 Data.AppliedToPointee = AppliedToPointee;
1533 StringRef Name,
const AttrVec *Attrs =
nullptr,
1548 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1555 bool RefersToCapture =
false) {
1566 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1568 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1569 "Additional reduction info may be specified only for reduction items.");
1570 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1571 assert(ReductionData.ReductionRange.isInvalid() &&
1572 (getTopOfStack().
Directive == OMPD_taskgroup ||
1576 "Additional reduction info may be specified only once for reduction "
1578 ReductionData.set(BOK, SR);
1579 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1580 if (!TaskgroupReductionRef) {
1583 TaskgroupReductionRef =
1589 const Expr *ReductionRef) {
1591 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1593 getTopOfStack().SharingMap[
D].Attributes == OMPC_reduction &&
1594 "Additional reduction info may be specified only for reduction items.");
1595 ReductionData &ReductionData = getTopOfStack().ReductionMap[
D];
1596 assert(ReductionData.ReductionRange.isInvalid() &&
1597 (getTopOfStack().
Directive == OMPD_taskgroup ||
1601 "Additional reduction info may be specified only once for reduction "
1603 ReductionData.set(ReductionRef, SR);
1604 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1605 if (!TaskgroupReductionRef) {
1608 TaskgroupReductionRef =
1613const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1615 Expr *&TaskgroupDescriptor)
const {
1617 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1618 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1619 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1620 if (
Data.Attributes != OMPC_reduction ||
1621 Data.Modifier != OMPC_REDUCTION_task)
1623 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1624 if (!ReductionData.ReductionOp ||
1625 ReductionData.ReductionOp.is<
const Expr *>())
1626 return DSAVarData();
1627 SR = ReductionData.ReductionRange;
1628 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1629 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1630 "expression for the descriptor is not "
1632 TaskgroupDescriptor = I->TaskgroupReductionRef;
1633 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1634 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1637 return DSAVarData();
1640const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1642 Expr *&TaskgroupDescriptor)
const {
1644 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1645 for (const_iterator I = begin() + 1,
E = end(); I !=
E; ++I) {
1646 const DSAInfo &
Data = I->SharingMap.lookup(
D);
1647 if (
Data.Attributes != OMPC_reduction ||
1648 Data.Modifier != OMPC_REDUCTION_task)
1650 const ReductionData &ReductionData = I->ReductionMap.lookup(
D);
1651 if (!ReductionData.ReductionOp ||
1652 !ReductionData.ReductionOp.is<
const Expr *>())
1653 return DSAVarData();
1654 SR = ReductionData.ReductionRange;
1655 ReductionRef = ReductionData.ReductionOp.get<
const Expr *>();
1656 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1657 "expression for the descriptor is not "
1659 TaskgroupDescriptor = I->TaskgroupReductionRef;
1660 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1661 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1664 return DSAVarData();
1667bool DSAStackTy::isOpenMPLocal(
VarDecl *
D, const_iterator I)
const {
1669 for (const_iterator
E = end(); I !=
E; ++I) {
1670 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1674 Scope *CurScope = getCurScope();
1675 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(
D))
1677 return CurScope != TopScope;
1680 if (I->Context == DC)
1689 bool AcceptIfMutable =
true,
1690 bool *IsClassType =
nullptr) {
1692 Type =
Type.getNonReferenceType().getCanonicalType();
1693 bool IsConstant =
Type.isConstant(Context);
1698 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1700 RD = CTD->getTemplatedDecl();
1703 return IsConstant && !(SemaRef.
getLangOpts().CPlusPlus && RD &&
1710 bool AcceptIfMutable =
true,
1711 bool ListItemNotVar =
false) {
1715 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1716 : IsClassType ? diag::err_omp_const_not_mutable_variable
1717 : diag::err_omp_const_variable;
1718 SemaRef.
Diag(ELoc,
Diag) << getOpenMPClauseName(CKind);
1719 if (!ListItemNotVar &&
D) {
1720 const VarDecl *VD = dyn_cast<VarDecl>(
D);
1724 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1732const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(
ValueDecl *
D,
1737 auto *VD = dyn_cast<VarDecl>(
D);
1738 auto TI = Threadprivates.find(
D);
1739 if (TI != Threadprivates.end()) {
1740 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1741 DVar.CKind = OMPC_threadprivate;
1742 DVar.Modifier = TI->getSecond().Modifier;
1745 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1747 SemaRef, VD,
D->getType().getNonReferenceType(),
1748 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1749 DVar.CKind = OMPC_threadprivate;
1750 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1757 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1763 SemaRef, VD,
D->getType().getNonReferenceType(),
D->
getLocation());
1764 DVar.CKind = OMPC_threadprivate;
1765 addDSA(
D, DVar.RefExpr, OMPC_threadprivate);
1770 !isLoopControlVariable(
D).first) {
1771 const_iterator IterTarget =
1772 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1775 if (IterTarget != end()) {
1776 const_iterator ParentIterTarget = IterTarget + 1;
1777 for (const_iterator
Iter = begin();
Iter != ParentIterTarget; ++
Iter) {
1778 if (isOpenMPLocal(VD,
Iter)) {
1782 DVar.CKind = OMPC_threadprivate;
1786 if (!isClauseParsingMode() || IterTarget != begin()) {
1787 auto DSAIter = IterTarget->SharingMap.find(
D);
1788 if (DSAIter != IterTarget->SharingMap.end() &&
1790 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1791 DVar.CKind = OMPC_threadprivate;
1794 const_iterator End = end();
1796 D, std::distance(ParentIterTarget, End),
1800 IterTarget->ConstructLoc);
1801 DVar.CKind = OMPC_threadprivate;
1821 const_iterator I = begin();
1822 const_iterator EndI = end();
1823 if (FromParent && I != EndI)
1826 auto It = I->SharingMap.find(
D);
1827 if (It != I->SharingMap.end()) {
1828 const DSAInfo &
Data = It->getSecond();
1829 DVar.RefExpr =
Data.RefExpr.getPointer();
1830 DVar.PrivateCopy =
Data.PrivateCopy;
1831 DVar.CKind =
Data.Attributes;
1832 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1833 DVar.DKind = I->Directive;
1834 DVar.Modifier =
Data.Modifier;
1835 DVar.AppliedToPointee =
Data.AppliedToPointee;
1840 DVar.CKind = OMPC_shared;
1847 if (SemaRef.
LangOpts.OpenMP <= 31) {
1855 DSAVarData DVarTemp = hasInnermostDSA(
1858 return C == OMPC_firstprivate ||
C == OMPC_shared;
1860 MatchesAlways, FromParent);
1861 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1864 DVar.CKind = OMPC_shared;
1871 const_iterator I = begin();
1872 const_iterator EndI = end();
1873 if (FromParent && I != EndI)
1877 auto It = I->SharingMap.find(
D);
1878 if (It != I->SharingMap.end()) {
1879 const DSAInfo &
Data = It->getSecond();
1880 DVar.RefExpr =
Data.RefExpr.getPointer();
1881 DVar.PrivateCopy =
Data.PrivateCopy;
1882 DVar.CKind =
Data.Attributes;
1883 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1884 DVar.DKind = I->Directive;
1885 DVar.Modifier =
Data.Modifier;
1886 DVar.AppliedToPointee =
Data.AppliedToPointee;
1892const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1893 bool FromParent)
const {
1894 if (isStackEmpty()) {
1896 return getDSA(I,
D);
1899 const_iterator StartI = begin();
1900 const_iterator EndI = end();
1901 if (FromParent && StartI != EndI)
1903 return getDSA(StartI,
D);
1906const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(
ValueDecl *
D,
1907 unsigned Level)
const {
1908 if (getStackSize() <= Level)
1909 return DSAVarData();
1911 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1912 return getDSA(StartI,
D);
1915const DSAStackTy::DSAVarData
1918 DefaultDataSharingAttributes)>
1921 bool FromParent)
const {
1925 const_iterator I = begin();
1926 const_iterator EndI = end();
1927 if (FromParent && I != EndI)
1929 for (; I != EndI; ++I) {
1930 if (!DPred(I->Directive) &&
1931 !isImplicitOrExplicitTaskingRegion(I->Directive))
1933 const_iterator NewI = I;
1934 DSAVarData DVar = getDSA(NewI,
D);
1935 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1941const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1944 bool FromParent)
const {
1948 const_iterator StartI = begin();
1949 const_iterator EndI = end();
1950 if (FromParent && StartI != EndI)
1952 if (StartI == EndI || !DPred(StartI->Directive))
1954 const_iterator NewI = StartI;
1955 DSAVarData DVar = getDSA(NewI,
D);
1956 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1961bool DSAStackTy::hasExplicitDSA(
1964 unsigned Level,
bool NotLastprivate)
const {
1965 if (getStackSize() <= Level)
1968 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1969 auto I = StackElem.SharingMap.find(
D);
1970 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1971 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1972 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1975 auto LI = StackElem.LCVMap.find(
D);
1976 if (LI != StackElem.LCVMap.end())
1977 return CPred(OMPC_private,
false);
1981bool DSAStackTy::hasExplicitDirective(
1983 unsigned Level)
const {
1984 if (getStackSize() <= Level)
1986 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1987 return DPred(StackElem.Directive);
1990bool DSAStackTy::hasDirective(
1994 bool FromParent)
const {
1996 size_t Skip = FromParent ? 2 : 1;
1997 for (const_iterator I = begin() + std::min(Skip, getStackSize()),
E = end();
1999 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2005void SemaOpenMP::InitDataSharingAttributesStack() {
2006 VarDataSharingAttributesStack =
new DSAStackTy(
SemaRef);
2009#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2011void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2019 "Expected OpenMP device compilation.");
2025enum class FunctionEmissionStatus {
2036 "Expected OpenMP device compilation.");
2038 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2043 Kind = SemaDiagnosticBuilder::K_Immediate;
2054 ? SemaDiagnosticBuilder::K_Deferred
2055 : SemaDiagnosticBuilder::K_Immediate;
2059 Kind = SemaDiagnosticBuilder::K_Nop;
2062 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2074 "Expected OpenMP host compilation.");
2076 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2081 Kind = SemaDiagnosticBuilder::K_Immediate;
2084 Kind = SemaDiagnosticBuilder::K_Deferred;
2089 Kind = SemaDiagnosticBuilder::K_Nop;
2099 if (LO.OpenMP <= 45) {
2101 return OMPC_DEFAULTMAP_scalar;
2102 return OMPC_DEFAULTMAP_aggregate;
2105 return OMPC_DEFAULTMAP_pointer;
2107 return OMPC_DEFAULTMAP_scalar;
2108 return OMPC_DEFAULTMAP_aggregate;
2112 unsigned OpenMPCaptureLevel)
const {
2113 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2116 bool IsByRef =
true;
2122 bool IsVariableUsedInMapClause =
false;
2184 bool IsVariableAssociatedWithSection =
false;
2186 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2188 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2195 if (WhereFoundClauseKind != OMPC_map &&
2196 WhereFoundClauseKind != OMPC_has_device_addr)
2199 auto EI = MapExprComponents.rbegin();
2200 auto EE = MapExprComponents.rend();
2202 assert(EI != EE &&
"Invalid map expression!");
2204 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2205 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() ==
D;
2210 auto Last = std::prev(EE);
2212 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2213 if ((UO && UO->getOpcode() == UO_Deref) ||
2214 isa<ArraySubscriptExpr>(
Last->getAssociatedExpression()) ||
2215 isa<ArraySectionExpr>(
Last->getAssociatedExpression()) ||
2216 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2217 isa<OMPArrayShapingExpr>(
Last->getAssociatedExpression())) {
2218 IsVariableAssociatedWithSection =
true;
2227 if (IsVariableUsedInMapClause) {
2230 IsByRef = !(Ty->
isPointerType() && IsVariableAssociatedWithSection);
2235 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2238 DSAStack->isDefaultmapCapturedByRef(
2243 return K == OMPC_reduction && !AppliedToPointee;
2251 ((IsVariableUsedInMapClause &&
2252 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2257 return K == OMPC_firstprivate ||
2258 (K == OMPC_reduction && AppliedToPointee);
2261 DSAStack->isUsesAllocatorsDecl(Level,
D))) &&
2264 !(isa<OMPCapturedExprDecl>(
D) && !
D->
hasAttr<OMPCaptureNoInitAttr>() &&
2265 !cast<OMPCapturedExprDecl>(
D)->getInit()->isGLValue()) &&
2268 !((
DSAStack->getDefaultDSA() == DSA_firstprivate ||
2269 DSAStack->getDefaultDSA() == DSA_private) &&
2273 !
DSAStack->isLoopControlVariable(
D, Level).first);
2290unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2292 return DSAStack->getNestingLevel();
2302 !
DSAStack->isClauseParsingMode()) ||
2313 if (!dyn_cast<FieldDecl>(
D))
2315 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2318 DefaultDataSharingAttributes DefaultAttr) {
2320 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2324 if (DVarPrivate.CKind != OMPC_unknown)
2330 Expr *CaptureExpr,
bool WithInit,
2336 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2339 auto *VD = dyn_cast<VarDecl>(
D);
2348 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2358 DSAStackTy::DSAVarData DVarTop =
2360 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2365 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2372 if (!isa<CapturingScopeInfo>(FSI))
2374 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2380 assert(CSI &&
"Failed to find CapturedRegionScopeInfo");
2391 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2397 if (CheckScopeInfo) {
2398 bool OpenMPFound =
false;
2399 for (
unsigned I = StopAt + 1; I > 0; --I) {
2401 if (!isa<CapturingScopeInfo>(FSI))
2403 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2413 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2414 (!
DSAStack->isClauseParsingMode() ||
2415 DSAStack->getParentDirective() != OMPD_unknown)) {
2416 auto &&Info =
DSAStack->isLoopControlVariable(
D);
2419 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2420 (VD &&
DSAStack->isForceVarCapturing()))
2421 return VD ? VD : Info.second;
2422 DSAStackTy::DSAVarData DVarTop =
2424 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2426 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2432 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2440 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2441 ((
DSAStack->getDefaultDSA() != DSA_none &&
2442 DSAStack->getDefaultDSA() != DSA_private &&
2443 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2444 DVarTop.CKind == OMPC_shared))
2446 auto *FD = dyn_cast<FieldDecl>(
D);
2447 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2448 !DVarPrivate.PrivateCopy) {
2449 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2452 DefaultDataSharingAttributes DefaultAttr) {
2454 (DefaultAttr == DSA_firstprivate ||
2455 DefaultAttr == DSA_private);
2459 if (DVarPrivate.CKind == OMPC_unknown)
2482 VD = cast<VarDecl>(VDPrivateRefExpr->
getDecl());
2483 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2486 if (DVarPrivate.CKind != OMPC_unknown ||
2487 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2488 DSAStack->getDefaultDSA() == DSA_private ||
2489 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2490 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2495void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2496 unsigned Level)
const {
2501 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2507 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2509 DSAStack->resetPossibleLoopCounter();
2515 unsigned CapLevel)
const {
2516 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2517 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2518 (!
DSAStack->isClauseParsingMode() ||
2519 DSAStack->getParentDirective() != OMPD_unknown)) {
2520 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2523 DefaultDataSharingAttributes DefaultAttr) {
2525 DefaultAttr == DSA_private;
2529 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(
D) &&
2530 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(
D)) &&
2531 !
DSAStack->isLoopControlVariable(
D).first)
2532 return OMPC_private;
2535 bool IsTriviallyCopyable =
2536 D->getType().getNonReferenceType().isTriviallyCopyableType(
2539 .getNonReferenceType()
2541 ->getAsCXXRecordDecl();
2546 (IsTriviallyCopyable ||
2552 return OMPC_firstprivate;
2553 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2554 if (DVar.CKind != OMPC_shared &&
2555 !
DSAStack->isLoopControlVariable(
D, Level).first && !DVar.RefExpr) {
2556 DSAStack->addImplicitTaskFirstprivate(Level,
D);
2557 return OMPC_firstprivate;
2566 return OMPC_private;
2569 DSAStack->isLoopControlVariable(
D).first) &&
2574 return OMPC_private;
2576 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2582 return OMPC_private;
2587 DSAStack->isUsesAllocatorsDecl(Level,
D).value_or(
2588 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2589 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2590 return OMPC_private;
2594 (
DSAStack->isClauseParsingMode() &&
2595 DSAStack->getClauseParsingMode() == OMPC_private) ||
2600 return K == OMPD_taskgroup ||
2601 ((isOpenMPParallelDirective(K) ||
2602 isOpenMPWorksharingDirective(K)) &&
2603 !isOpenMPSimdDirective(K));
2606 DSAStack->isTaskgroupReductionRef(
D, Level)))
2613 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2616 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2617 const unsigned NewLevel = I - 1;
2621 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2629 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2639 if (
DSAStack->mustBeFirstprivateAtLevel(
2641 OMPC = OMPC_firstprivate;
2645 if (OMPC != OMPC_unknown)
2647 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2651 unsigned CaptureLevel)
const {
2652 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2657 const auto *VD = dyn_cast<VarDecl>(
D);
2661 Regions[CaptureLevel] != OMPD_task;
2665 unsigned CaptureLevel)
const {
2666 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2669 if (
const auto *VD = dyn_cast<VarDecl>(
D)) {
2673 DSAStackTy::DSAVarData TopDVar =
2675 unsigned NumLevels =
2680 return (NumLevels == CaptureLevel + 1 &&
2681 (TopDVar.CKind != OMPC_shared ||
2682 DSAStack->getDefaultDSA() == DSA_firstprivate));
2685 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(
D, Level);
2686 if (DVar.CKind != OMPC_shared)
2688 }
while (Level > 0);
2694void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2698 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2703 "Not in OpenMP declare variant scope!");
2705 OMPDeclareVariantScopes.pop_back();
2711 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2712 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2716 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2719 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2720 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2723 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2724 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2725 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2727 StringRef HostDevTy =
2729 Diag(
Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2730 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2731 diag::note_omp_marked_device_type_here)
2737 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2741 for (OMPDeclareVariantAttr *A :
2742 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2743 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2744 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2745 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2746 OMPDeclareTargetDeclAttr::getDeviceType(
2747 VariantFD->getMostRecentDecl());
2748 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2754 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2758 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2759 Diag(
Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2760 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2761 diag::note_omp_marked_device_type_here)
2779 DSAStack->setClauseParsingMode(OMPC_unknown);
2783static std::pair<ValueDecl *, bool>
2785 SourceRange &ERange,
bool AllowArraySection =
false,
2786 StringRef DiagType =
"");
2791 bool InscanFound =
false;
2798 if (
C->getClauseKind() != OMPC_reduction)
2800 auto *RC = cast<OMPReductionClause>(
C);
2801 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2803 InscanLoc = RC->getModifierLoc();
2806 if (RC->getModifier() == OMPC_REDUCTION_task) {
2816 S.
Diag(RC->getModifierLoc(),
2817 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2823 if (
C->getClauseKind() != OMPC_reduction)
2825 auto *RC = cast<OMPReductionClause>(
C);
2826 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2829 : RC->getModifierLoc(),
2830 diag::err_omp_inscan_reduction_expected);
2831 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2834 for (
Expr *Ref : RC->varlist()) {
2835 assert(Ref &&
"NULL expr in OpenMP nontemporal clause.");
2838 Expr *SimpleRefExpr = Ref;
2845 S.
Diag(Ref->getExprLoc(),
2846 diag::err_omp_reduction_not_inclusive_exclusive)
2847 << Ref->getSourceRange();
2861 const DSAStackTy::DSAVarData &DVar,
2862 bool IsLoopIterVar =
false);
2870 if (
const auto *
D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2872 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
2874 for (
Expr *DE : Clause->varlist()) {
2875 if (DE->isValueDependent() || DE->isTypeDependent()) {
2876 PrivateCopies.push_back(
nullptr);
2879 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2880 auto *VD = cast<VarDecl>(DRE->getDecl());
2882 const DSAStackTy::DSAVarData DVar =
2884 if (DVar.CKind == OMPC_lastprivate) {
2891 SemaRef, DE->getExprLoc(),
Type.getUnqualifiedType(),
2895 PrivateCopies.push_back(
nullptr);
2903 PrivateCopies.push_back(
nullptr);
2906 Clause->setPrivateCopies(PrivateCopies);
2910 if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
2912 for (
Expr *RefExpr : Clause->varlist()) {
2913 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
2916 Expr *SimpleRefExpr = RefExpr;
2920 PrivateRefs.push_back(RefExpr);
2925 const DSAStackTy::DSAVarData DVar =
2927 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2930 Clause->setPrivateRefs(PrivateRefs);
2933 if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
2934 for (
unsigned I = 0,
E = Clause->getNumberOfAllocators(); I <
E; ++I) {
2936 auto *DRE = dyn_cast<DeclRefExpr>(
D.Allocator->IgnoreParenImpCasts());
2940 if (!VD || !isa<VarDecl>(VD))
2942 DSAStackTy::DSAVarData DVar =
2948 Expr *MapExpr =
nullptr;
2950 DSAStack->checkMappableExprComponentListsForDecl(
2956 auto MI = MapExprComponents.rbegin();
2957 auto ME = MapExprComponents.rend();
2959 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2960 VD->getCanonicalDecl()) {
2961 MapExpr = MI->getAssociatedExpression();
2966 Diag(
D.Allocator->getExprLoc(),
2967 diag::err_omp_allocator_used_in_clauses)
2972 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2973 << MapExpr->getSourceRange();
2991 Expr *NumIterations,
Sema &SemaRef,
2992 Scope *S, DSAStackTy *Stack);
2996 DSAStackTy *Stack) {
2998 "loop exprs were not built");
3005 auto *LC = dyn_cast<OMPLinearClause>(
C);
3024 explicit VarDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3025 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3027 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3035 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3036 return std::make_unique<VarDeclFilterCCC>(*
this);
3045 explicit VarOrFuncDeclFilterCCC(
Sema &S) : SemaRef(S) {}
3046 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3048 if (ND && ((isa<VarDecl>(ND) && ND->
getKind() == Decl::Var) ||
3049 isa<FunctionDecl>(ND))) {
3056 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3057 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3078 VarDeclFilterCCC CCC(
SemaRef);
3085 : diag::err_omp_expected_var_arg_suggest)
3087 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3089 Diag(
Id.getLoc(), Lookup.
empty() ? diag::err_undeclared_var_use
3090 : diag::err_omp_expected_var_arg)
3095 Diag(
Id.getLoc(), diag::err_omp_expected_var_arg) <<
Id.getName();
3104 Diag(
Id.getLoc(), diag::err_omp_global_var_arg)
3109 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3121 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3122 << getOpenMPDirectiveName(Kind) << VD;
3126 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3136 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3137 << getOpenMPDirectiveName(Kind) << VD;
3141 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3153 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3154 << getOpenMPDirectiveName(Kind) << VD;
3158 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3167 Diag(
Id.getLoc(), diag::err_omp_var_scope)
3168 << getOpenMPDirectiveName(Kind) << VD;
3172 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3180 if (Kind == OMPD_threadprivate && VD->
isUsed() &&
3182 Diag(
Id.getLoc(), diag::err_omp_var_used)
3183 << getOpenMPDirectiveName(Kind) << VD;
3205class LocalVarRefChecker final
3211 if (
const auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3214 diag::err_omp_local_var_in_threadprivate_init)
3216 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3223 bool VisitStmt(
const Stmt *S) {
3224 for (
const Stmt *Child : S->children()) {
3225 if (Child && Visit(Child))
3230 explicit LocalVarRefChecker(
Sema &SemaRef) : SemaRef(SemaRef) {}
3239 for (
Expr *RefExpr : VarList) {
3240 auto *DE = cast<DeclRefExpr>(RefExpr);
3241 auto *VD = cast<VarDecl>(DE->getDecl());
3258 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3265 Diag(ILoc, diag::err_omp_ref_type_arg)
3266 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->
getType();
3270 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3278 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3283 Diag(ILoc, diag::err_omp_var_thread_local)
3288 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3296 LocalVarRefChecker Checker(
SemaRef);
3297 if (Checker.Visit(
Init))
3301 Vars.push_back(RefExpr);
3302 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3303 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3306 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3309 if (!Vars.empty()) {
3317static OMPAllocateDeclAttr::AllocatorTypeTy
3320 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3321 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3322 Allocator->isInstantiationDependent() ||
3323 Allocator->containsUnexpandedParameterPack())
3324 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3325 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3326 llvm::FoldingSetNodeID AEId;
3327 const Expr *AE = Allocator->IgnoreParenImpCasts();
3329 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3330 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3331 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3332 llvm::FoldingSetNodeID DAEId;
3335 if (AEId == DAEId) {
3336 AllocatorKindRes = AllocatorKind;
3340 return AllocatorKindRes;
3345 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3346 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3348 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3349 Expr *PrevAllocator = A->getAllocator();
3350 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3352 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3353 if (AllocatorsMatch &&
3354 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3355 Allocator && PrevAllocator) {
3356 const Expr *AE = Allocator->IgnoreParenImpCasts();
3358 llvm::FoldingSetNodeID AEId, PAEId;
3361 AllocatorsMatch = AEId == PAEId;
3363 if (!AllocatorsMatch) {
3365 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3369 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3371 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3375 Allocator ? Allocator->getExprLoc() : RefExpr->
getExprLoc();
3377 Allocator ? Allocator->getSourceRange() : RefExpr->
getSourceRange();
3379 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3381 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3382 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3383 << (Allocator ? 1 : 0) << AllocatorStream.str()
3384 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3386 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3387 << PrevAllocatorRange;
3395 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3397 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3406 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3407 Allocator->isInstantiationDependent() ||
3408 Allocator->containsUnexpandedParameterPack()))
3410 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3411 Allocator, Alignment, SR);
3414 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3420 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3421 Expr *Alignment =
nullptr;
3422 Expr *Allocator =
nullptr;
3423 if (Clauses.empty()) {
3433 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3434 Allocator = AC->getAllocator();
3435 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3436 Alignment = AC->getAlignment();
3438 llvm_unreachable(
"Unexpected clause on allocate directive");
3440 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3443 for (
Expr *RefExpr : VarList) {
3444 auto *DE = cast<DeclRefExpr>(RefExpr);
3445 auto *VD = cast<VarDecl>(DE->getDecl());
3449 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3457 AllocatorKind, Allocator))
3465 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3466 Diag(Allocator->getExprLoc(),
3467 diag::err_omp_expected_predefined_allocator)
3468 << Allocator->getSourceRange();
3472 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3478 Vars.push_back(RefExpr);
3497 Diag(
Loc, diag::err_omp_invalid_scope) <<
"requires";
3511 bool SkippedClauses) {
3512 if (!SkippedClauses && Assumptions.empty())
3513 Diag(
Loc, diag::err_omp_no_clause_for_directive)
3514 << llvm::omp::getAllAssumeClauseOptions()
3515 << llvm::omp::getOpenMPDirectiveName(DKind);
3519 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3520 OMPAssumeScoped.push_back(AA);
3525 if (Assumptions.empty())
3528 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3529 "Unexpected omp assumption directive!");
3530 OMPAssumeGlobal.push_back(AA);
3538 while (Ctx->getLexicalParent())
3540 DeclContexts.push_back(Ctx);
3541 while (!DeclContexts.empty()) {
3543 for (
auto *SubDC : DC->
decls()) {
3544 if (SubDC->isInvalidDecl())
3546 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3547 DeclContexts.push_back(CTD->getTemplatedDecl());
3548 llvm::append_range(DeclContexts, CTD->specializations());
3551 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3552 DeclContexts.push_back(DC);
3553 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3563 OMPAssumeScoped.pop_back();
3584 DSAStack->getEncounteredTargetLocs();
3586 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3587 for (
const OMPClause *CNew : ClauseList) {
3589 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3590 isa<OMPUnifiedAddressClause>(CNew) ||
3591 isa<OMPReverseOffloadClause>(CNew) ||
3592 isa<OMPDynamicAllocatorsClause>(CNew)) {
3593 Diag(
Loc, diag::err_omp_directive_before_requires)
3594 <<
"target" << getOpenMPClauseName(CNew->getClauseKind());
3596 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3600 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3601 Diag(
Loc, diag::err_omp_directive_before_requires)
3602 <<
"atomic" << getOpenMPClauseName(CNew->getClauseKind());
3603 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3609 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3617 const DSAStackTy::DSAVarData &DVar,
3618 bool IsLoopIterVar) {
3620 SemaRef.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3621 << getOpenMPClauseName(DVar.CKind);
3625 PDSA_StaticMemberShared,
3626 PDSA_StaticLocalVarShared,
3627 PDSA_LoopIterVarPrivate,
3628 PDSA_LoopIterVarLinear,
3629 PDSA_LoopIterVarLastprivate,
3630 PDSA_ConstVarShared,
3631 PDSA_GlobalVarShared,
3632 PDSA_TaskVarFirstprivate,
3633 PDSA_LocalVarPrivate,
3635 } Reason = PDSA_Implicit;
3636 bool ReportHint =
false;
3638 auto *VD = dyn_cast<VarDecl>(
D);
3639 if (IsLoopIterVar) {
3640 if (DVar.CKind == OMPC_private)
3641 Reason = PDSA_LoopIterVarPrivate;
3642 else if (DVar.CKind == OMPC_lastprivate)
3643 Reason = PDSA_LoopIterVarLastprivate;
3645 Reason = PDSA_LoopIterVarLinear;
3647 DVar.CKind == OMPC_firstprivate) {
3648 Reason = PDSA_TaskVarFirstprivate;
3649 ReportLoc = DVar.ImplicitDSALoc;
3651 Reason = PDSA_StaticLocalVarShared;
3653 Reason = PDSA_StaticMemberShared;
3655 Reason = PDSA_GlobalVarShared;
3657 Reason = PDSA_ConstVarShared;
3658 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3660 Reason = PDSA_LocalVarPrivate;
3662 if (Reason != PDSA_Implicit) {
3663 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3664 << Reason << ReportHint
3665 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3666 }
else if (DVar.ImplicitDSALoc.isValid()) {
3667 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3668 << getOpenMPClauseName(DVar.CKind);
3674 bool IsAggregateOrDeclareTarget) {
3677 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3678 Kind = OMPC_MAP_alloc;
3680 case OMPC_DEFAULTMAP_MODIFIER_to:
3683 case OMPC_DEFAULTMAP_MODIFIER_from:
3684 Kind = OMPC_MAP_from;
3686 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3687 Kind = OMPC_MAP_tofrom;
3689 case OMPC_DEFAULTMAP_MODIFIER_present:
3695 Kind = OMPC_MAP_alloc;
3697 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3699 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3700 case OMPC_DEFAULTMAP_MODIFIER_none:
3701 case OMPC_DEFAULTMAP_MODIFIER_default:
3706 if (IsAggregateOrDeclareTarget) {
3707 Kind = OMPC_MAP_tofrom;
3710 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
3717class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
3720 bool ErrorFound =
false;
3721 bool TryCaptureCXXThisMembers =
false;
3728 ImplicitMapModifier[DefaultmapKindNum];
3730 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3734 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3736 if (S->getDirectiveKind() == OMPD_atomic ||
3737 S->getDirectiveKind() == OMPD_critical ||
3738 S->getDirectiveKind() == OMPD_section ||
3739 S->getDirectiveKind() == OMPD_master ||
3740 S->getDirectiveKind() == OMPD_masked ||
3741 S->getDirectiveKind() == OMPD_scope ||
3742 S->getDirectiveKind() == OMPD_assume ||
3744 Visit(S->getAssociatedStmt());
3747 visitSubCaptures(S->getInnermostCapturedStmt());
3750 if (TryCaptureCXXThisMembers ||
3752 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3754 return C.capturesThis();
3756 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3757 TryCaptureCXXThisMembers =
true;
3758 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3759 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3766 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
3767 for (
Expr *Ref : FC->varlist())
3780 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
3783 !Stack->getTopDSA(VD,
false).RefExpr &&
3784 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3785 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3786 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3787 Visit(CED->getInit());
3790 }
else if (VD->
isImplicit() || isa<OMPCapturedExprDecl>(VD))
3793 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3798 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3799 !Stack->isImplicitTaskFirstprivate(VD))
3802 if (Stack->isUsesAllocatorsDecl(VD))
3805 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
3807 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3811 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3812 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3815 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3816 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3817 !Stack->isImplicitTaskFirstprivate(VD))
3826 if (DVar.CKind == OMPC_unknown &&
3827 (Stack->getDefaultDSA() == DSA_none ||
3828 Stack->getDefaultDSA() == DSA_private ||
3829 Stack->getDefaultDSA() == DSA_firstprivate) &&
3830 isImplicitOrExplicitTaskingRegion(DKind) &&
3831 VarsWithInheritedDSA.count(VD) == 0) {
3832 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3833 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3834 Stack->getDefaultDSA() == DSA_private)) {
3835 DSAStackTy::DSAVarData DVar =
3836 Stack->getImplicitDSA(VD,
false);
3837 InheritedDSA = DVar.CKind == OMPC_unknown;
3840 VarsWithInheritedDSA[VD] =
E;
3841 if (Stack->getDefaultDSA() == DSA_none)
3856 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3857 OMPC_DEFAULTMAP_MODIFIER_none;
3858 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3859 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3863 if (!Stack->checkMappableExprComponentListsForDecl(
3868 auto MI = MapExprComponents.rbegin();
3869 auto ME = MapExprComponents.rend();
3870 return MI != ME && MI->getAssociatedDeclaration() == VD;
3872 VarsWithInheritedDSA[VD] =
E;
3878 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3879 OMPC_DEFAULTMAP_MODIFIER_present;
3880 if (IsModifierPresent) {
3881 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3882 OMPC_MAP_MODIFIER_present)) {
3883 ImplicitMapModifier[ClauseKind].push_back(
3884 OMPC_MAP_MODIFIER_present);
3890 !Stack->isLoopControlVariable(VD).first) {
3891 if (!Stack->checkMappableExprComponentListsForDecl(
3896 if (SemaRef.LangOpts.OpenMP >= 50)
3897 return !StackComponents.empty();
3900 return StackComponents.size() == 1 ||
3902 llvm::drop_begin(llvm::reverse(StackComponents)),
3903 [](const OMPClauseMappableExprCommon::
3904 MappableComponent &MC) {
3905 return MC.getAssociatedDeclaration() ==
3907 (isa<ArraySectionExpr>(
3908 MC.getAssociatedExpression()) ||
3909 isa<OMPArrayShapingExpr>(
3910 MC.getAssociatedExpression()) ||
3911 isa<ArraySubscriptExpr>(
3912 MC.getAssociatedExpression()));
3915 bool IsFirstprivate =
false;
3917 if (
const auto *RD =
3919 IsFirstprivate = RD->isLambda();
3921 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3922 if (IsFirstprivate) {
3923 ImplicitFirstprivate.emplace_back(
E);
3926 Stack->getDefaultmapModifier(ClauseKind);
3928 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3929 ImplicitMap[ClauseKind][
Kind].emplace_back(
E);
3939 DVar = Stack->hasInnermostDSA(
3942 return C == OMPC_reduction && !AppliedToPointee;
3951 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
3957 DVar = Stack->getImplicitDSA(VD,
false);
3959 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3960 DVar.CKind == OMPC_firstprivate) ||
3961 (Stack->getDefaultDSA() == DSA_private &&
3962 DVar.CKind == OMPC_private)) &&
3964 !Stack->isLoopControlVariable(VD).first) {
3965 if (Stack->getDefaultDSA() == DSA_private)
3966 ImplicitPrivate.push_back(
E);
3968 ImplicitFirstprivate.push_back(
E);
3975 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3976 Stack->addToParentTargetRegionLinkGlobals(
E);
3985 auto *FD = dyn_cast<FieldDecl>(
E->getMemberDecl());
3990 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
3993 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3997 !Stack->isLoopControlVariable(FD).first &&
3998 !Stack->checkMappableExprComponentListsForDecl(
4003 return isa<CXXThisExpr>(
4005 StackComponents.back().getAssociatedExpression())
4017 if (Stack->isClassPreviouslyMapped(TE->getType()))
4021 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4026 ImplicitMap[ClauseKind][
Kind].emplace_back(
E);
4035 DVar = Stack->hasInnermostDSA(
4038 return C == OMPC_reduction && !AppliedToPointee;
4047 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4053 DVar = Stack->getImplicitDSA(FD,
false);
4055 !Stack->isLoopControlVariable(FD).first) {
4060 if (DVar.CKind != OMPC_unknown)
4061 ImplicitFirstprivate.push_back(
E);
4068 Stack->getCurrentDirective(),
4071 const auto *VD = cast<ValueDecl>(
4072 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4073 if (!Stack->checkMappableExprComponentListsForDecl(
4079 auto CCI = CurComponents.rbegin();
4080 auto CCE = CurComponents.rend();
4081 for (const auto &SC : llvm::reverse(StackComponents)) {
4083 if (CCI->getAssociatedExpression()->getStmtClass() !=
4084 SC.getAssociatedExpression()->getStmtClass())
4085 if (!((isa<ArraySectionExpr>(
4086 SC.getAssociatedExpression()) ||
4087 isa<OMPArrayShapingExpr>(
4088 SC.getAssociatedExpression())) &&
4089 isa<ArraySubscriptExpr>(
4090 CCI->getAssociatedExpression())))
4093 const Decl *CCD = CCI->getAssociatedDeclaration();
4094 const Decl *SCD = SC.getAssociatedDeclaration();
4095 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4096 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4099 std::advance(CCI, 1);
4105 Visit(
E->getBase());
4107 }
else if (!TryCaptureCXXThisMembers) {
4108 Visit(
E->getBase());
4115 if (isa_and_nonnull<OMPPrivateClause>(
C))
4121 if (
C && !((isa<OMPFirstprivateClause>(
C) || isa<OMPMapClause>(
C)) &&
4124 for (
Stmt *CC :
C->children()) {
4131 VisitSubCaptures(S);
4140 for (
Stmt *
C : S->arguments()) {
4147 if (
Expr *Callee = S->getCallee()) {
4148 auto *CI =
Callee->IgnoreParenImpCasts();
4149 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4150 Visit(CE->getBase());
4151 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4155 void VisitStmt(
Stmt *S) {
4156 for (
Stmt *
C : S->children()) {
4167 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4169 VarDecl *VD = Cap.getCapturedVar();
4173 Stack->checkMappableExprComponentListsForDecl(
4180 Cap.getLocation(),
true);
4184 bool isErrorFound()
const {
return ErrorFound; }
4186 return ImplicitFirstprivate;
4191 return ImplicitMap[DK][MK];
4195 return ImplicitMapModifier[
Kind];
4198 return VarsWithInheritedDSA;
4202 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4217 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4219 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4221 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4223 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4225 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4226 Stack->handleConstructTrait(Traits, ScopeEntry);
4237 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4238 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4240 if (LoopBoundSharing) {
4242 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4243 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4247 Params.push_back(std::make_pair(StringRef(),
QualType()));
4268 std::make_pair(
".global_tid.", KmpInt32Ty),
4269 std::make_pair(
".part_id.", KmpInt32PtrTy),
4270 std::make_pair(
".privates.", VoidPtrTy),
4275 std::make_pair(StringRef(),
QualType())
4286 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4289 Params.push_back(std::make_pair(StringRef(),
QualType()));
4296 std::make_pair(StringRef(),
QualType())
4318 std::make_pair(
".global_tid.", KmpInt32Ty),
4319 std::make_pair(
".part_id.", KmpInt32PtrTy),
4320 std::make_pair(
".privates.", VoidPtrTy),
4325 std::make_pair(
".lb.", KmpUInt64Ty),
4326 std::make_pair(
".ub.", KmpUInt64Ty),
4327 std::make_pair(
".st.", KmpInt64Ty),
4328 std::make_pair(
".liter.", KmpInt32Ty),
4329 std::make_pair(
".reductions.", VoidPtrTy),
4330 std::make_pair(StringRef(),
QualType())
4343 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4344 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4347 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
4382 case OMPD_metadirective:
4385 llvm_unreachable(
"Unexpected capture region");
4401 case OMPD_interchange:
4414int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
4421 return CaptureRegions.size();
4425 Expr *CaptureExpr,
bool WithInit,
4427 bool AsExpression) {
4428 assert(CaptureExpr);
4434 Ty =
C.getLValueReferenceType(Ty);
4436 Ty =
C.getPointerType(Ty);
4448 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
4459 CD = cast<OMPCapturedExprDecl>(VD);
4498class CaptureRegionUnwinderRAII {
4505 CaptureRegionUnwinderRAII(
Sema &S,
bool &ErrorFound,
4507 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4508 ~CaptureRegionUnwinderRAII() {
4511 while (--ThisCaptureLevel >= 0)
4524 DSAStack->getCurrentDirective()))) {
4526 if (
const auto *RD =
Type.getCanonicalType()
4527 .getNonReferenceType()
4529 bool SavedForceCaptureByReferenceInTargetExecutable =
4530 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4531 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4533 if (RD->isLambda()) {
4534 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4536 RD->getCaptureFields(Captures, ThisCapture);
4539 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4544 }
else if (LC.getCaptureKind() ==
LCK_This) {
4547 ThisTy, ThisCapture->
getType()))
4552 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4553 SavedForceCaptureByReferenceInTargetExecutable);
4563 for (
const OMPClause *Clause : Clauses) {
4565 Ordered = cast<OMPOrderedClause>(Clause);
4567 Order = cast<OMPOrderClause>(Clause);
4568 if (Order->
getKind() != OMPC_ORDER_concurrent)
4571 if (Ordered && Order)
4575 if (Ordered && Order) {
4577 diag::err_omp_simple_clause_incompatible_with_ordered)
4578 << getOpenMPClauseName(OMPC_order)
4595 bool ErrorFound =
false;
4596 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4598 if (!S.isUsable()) {
4613 DSAStack->getCurrentDirective() == OMPD_target) &&
4617 auto *IRC = cast<OMPInReductionClause>(Clause);
4618 for (
Expr *
E : IRC->taskgroup_descriptors())
4630 if (
auto *
E = cast_or_null<Expr>(VarRef)) {
4634 DSAStack->setForceVarCapturing(
false);
4635 }
else if (CaptureRegions.size() > 1 ||
4636 CaptureRegions.back() != OMPD_unknown) {
4640 if (
Expr *
E =
C->getPostUpdateExpr())
4645 SC = cast<OMPScheduleClause>(Clause);
4647 OC = cast<OMPOrderedClause>(Clause);
4649 LCs.push_back(cast<OMPLinearClause>(Clause));
4660 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4665 diag::err_omp_simple_clause_incompatible_with_ordered)
4666 << getOpenMPClauseName(OMPC_schedule)
4668 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4679 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
4688 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
4695 unsigned CompletedRegions = 0;
4700 if (ThisCaptureRegion != OMPD_unknown) {
4708 if (CaptureRegion == ThisCaptureRegion ||
4709 CaptureRegion == OMPD_unknown) {
4710 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
4711 for (
Decl *
D : DS->decls())
4718 if (ThisCaptureRegion == OMPD_target) {
4722 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
4723 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4726 if (
Expr *
E =
D.AllocatorTraits)
4733 if (ThisCaptureRegion == OMPD_parallel) {
4737 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
4738 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4740 for (
Expr *
E : RC->copy_array_temps())
4744 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
4745 for (
Expr *
E : AC->varlist())
4750 if (++CompletedRegions == CaptureRegions.size())
4761 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4764 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4765 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4768 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4769 << getOpenMPDirectiveName(CancelRegion);
4779 if (!Stack->getCurScope())
4784 bool NestingProhibited =
false;
4785 bool CloseNesting =
true;
4786 bool OrphanSeen =
false;
4789 ShouldBeInParallelRegion,
4790 ShouldBeInOrderedRegion,
4791 ShouldBeInTargetRegion,
4792 ShouldBeInTeamsRegion,
4793 ShouldBeInLoopSimdRegion,
4794 } Recommend = NoRecommend;
4798 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4801 if (SemaRef.
LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4802 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4803 CurrentRegion != OMPD_parallel &&
4805 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
4806 << getOpenMPDirectiveName(CurrentRegion);
4810 ((SemaRef.
LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4811 (SemaRef.
LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4812 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4813 CurrentRegion != OMPD_scan))) {
4826 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
4827 ? diag::err_omp_prohibited_region_simd
4828 : diag::warn_omp_nesting_simd)
4829 << (SemaRef.
LangOpts.OpenMP >= 50 ? 1 : 0);
4830 return CurrentRegion != OMPD_simd;
4832 if (EnclosingConstruct == OMPD_atomic) {
4835 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4838 if (CurrentRegion == OMPD_section) {
4843 if (EnclosingConstruct != OMPD_sections) {
4844 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4845 << (ParentRegion != OMPD_unknown)
4846 << getOpenMPDirectiveName(ParentRegion);
4854 if (ParentRegion == OMPD_unknown &&
4856 CurrentRegion != OMPD_cancellation_point &&
4857 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4861 if (SemaRef.
LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4862 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4864 EnclosingConstruct == OMPD_loop)) {
4865 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4866 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
4867 <<
true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4868 << getOpenMPDirectiveName(CurrentRegion);
4871 if (CurrentRegion == OMPD_cancellation_point ||
4872 CurrentRegion == OMPD_cancel) {
4885 if (CancelRegion == OMPD_taskgroup) {
4886 NestingProhibited = EnclosingConstruct != OMPD_task &&
4888 EnclosingConstruct != OMPD_taskloop);
4889 }
else if (CancelRegion == OMPD_sections) {
4890 NestingProhibited = EnclosingConstruct != OMPD_section &&
4891 EnclosingConstruct != OMPD_sections;
4893 NestingProhibited = CancelRegion != Leafs.back();
4895 OrphanSeen = ParentRegion == OMPD_unknown;
4896 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4903 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
4909 bool DeadLock = Stack->hasDirective(
4913 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
4914 PreviousCriticalLoc = Loc;
4921 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4923 if (PreviousCriticalLoc.
isValid())
4924 SemaRef.
Diag(PreviousCriticalLoc,
4925 diag::note_omp_previous_critical_region);
4928 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4938 llvm::is_contained({OMPD_masked, OMPD_master,
4939 OMPD_critical, OMPD_ordered},
4940 EnclosingConstruct);
4951 llvm::is_contained({OMPD_masked, OMPD_master,
4952 OMPD_critical, OMPD_ordered},
4953 EnclosingConstruct);
4954 Recommend = ShouldBeInParallelRegion;
4955 }
else if (CurrentRegion == OMPD_ordered) {
4964 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4967 Stack->isParentOrderedRegion());
4968 Recommend = ShouldBeInOrderedRegion;
4974 (SemaRef.
LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4975 (SemaRef.
LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4976 EnclosingConstruct != OMPD_target);
4977 OrphanSeen = ParentRegion == OMPD_unknown;
4978 Recommend = ShouldBeInTargetRegion;
4979 }
else if (CurrentRegion == OMPD_scan) {
4980 if (SemaRef.
LangOpts.OpenMP >= 50) {
4985 NestingProhibited = !llvm::is_contained(
4986 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4988 NestingProhibited =
true;
4990 OrphanSeen = ParentRegion == OMPD_unknown;
4991 Recommend = ShouldBeInLoopSimdRegion;
4995 EnclosingConstruct == OMPD_teams) {
5007 CurrentRegion != OMPD_loop &&
5009 CurrentRegion == OMPD_atomic);
5010 Recommend = ShouldBeInParallelRegion;
5012 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5018 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5019 Recommend = ShouldBeInTeamsRegion;
5025 NestingProhibited = EnclosingConstruct != OMPD_teams;
5026 Recommend = ShouldBeInTeamsRegion;
5028 if (!NestingProhibited &&
5035 NestingProhibited = Stack->hasDirective(
5039 OffendingRegion = K;
5045 CloseNesting =
false;
5047 if (NestingProhibited) {
5049 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5050 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5052 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5053 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5054 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5068 bool ErrorFound =
false;
5069 unsigned NamedModifiersNumber = 0;
5070 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5071 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5074 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5078 if (FoundNameModifiers[CurNM]) {
5079 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5080 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5081 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5083 }
else if (CurNM != OMPD_unknown) {
5084 NameModifierLoc.push_back(IC->getNameModifierLoc());
5085 ++NamedModifiersNumber;
5087 FoundNameModifiers[CurNM] = IC;
5088 if (CurNM == OMPD_unknown)
5094 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5095 S.
Diag(IC->getNameModifierLoc(),
5096 diag::err_omp_wrong_if_directive_name_modifier)
5097 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5104 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5105 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5106 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5107 diag::err_omp_no_more_if_clause);
5110 std::string Sep(
", ");
5111 unsigned AllowedCnt = 0;
5112 unsigned TotalAllowedNum =
5113 AllowedNameModifiers.size() - NamedModifiersNumber;
5114 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5117 if (!FoundNameModifiers[NM]) {
5119 Values += getOpenMPDirectiveName(NM);
5121 if (AllowedCnt + 2 == TotalAllowedNum)
5123 else if (AllowedCnt + 1 != TotalAllowedNum)
5128 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5129 diag::err_omp_unnamed_if_clause)
5130 << (TotalAllowedNum > 1) << Values;
5133 S.
Diag(
Loc, diag::note_omp_previous_named_if_clause);
5143 bool AllowArraySection,
5144 StringRef DiagType) {
5147 return std::make_pair(
nullptr,
true);
5159 } IsArrayExpr = NoArrayExpr;
5160 if (AllowArraySection) {
5161 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5162 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5163 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5164 Base = TempASE->getBase()->IgnoreParenImpCasts();
5166 IsArrayExpr = ArraySubscript;
5167 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5168 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5169 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5170 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5171 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5172 Base = TempASE->getBase()->IgnoreParenImpCasts();
5174 IsArrayExpr = OMPArraySection;
5180 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5181 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5182 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5184 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5185 !isa<FieldDecl>(ME->getMemberDecl()))) {
5186 if (IsArrayExpr != NoArrayExpr) {
5187 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5188 << IsArrayExpr << ERange;
5189 }
else if (!DiagType.empty()) {
5193 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5194 << DiagSelect << DiagType << ERange;
5198 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5199 : diag::err_omp_expected_var_name_member_expr)
5202 return std::make_pair(
nullptr,
false);
5204 return std::make_pair(
5211class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5212 DSAStackTy *S =
nullptr;
5216 return S->isUsesAllocatorsDecl(
E->getDecl())
5217 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5218 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5220 bool VisitStmt(
const Stmt *S) {
5221 for (
const Stmt *Child : S->children()) {
5222 if (Child && Visit(Child))
5227 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5234 "Expected non-dependent context.");
5235 auto AllocateRange =
5238 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5243 if (
Cl->getClauseKind() == OMPC_private) {
5244 auto *PC = cast<OMPPrivateClause>(
Cl);
5245 I = PC->private_copies().begin();
5246 It = PC->varlist_begin();
5247 Et = PC->varlist_end();
5248 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5249 auto *PC = cast<OMPFirstprivateClause>(
Cl);
5250 I = PC->private_copies().begin();
5251 It = PC->varlist_begin();
5252 Et = PC->varlist_end();
5253 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5254 auto *PC = cast<OMPLastprivateClause>(
Cl);
5255 I = PC->private_copies().begin();
5256 It = PC->varlist_begin();
5257 Et = PC->varlist_end();
5258 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5259 auto *PC = cast<OMPLinearClause>(
Cl);
5260 I = PC->privates().begin();
5261 It = PC->varlist_begin();
5262 Et = PC->varlist_end();
5263 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5264 auto *PC = cast<OMPReductionClause>(
Cl);
5265 I = PC->privates().begin();
5266 It = PC->varlist_begin();
5267 Et = PC->varlist_end();
5268 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5269 auto *PC = cast<OMPTaskReductionClause>(
Cl);
5270 I = PC->privates().begin();
5271 It = PC->varlist_begin();
5272 Et = PC->varlist_end();
5273 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5274 auto *PC = cast<OMPInReductionClause>(
Cl);
5275 I = PC->privates().begin();
5276 It = PC->varlist_begin();
5277 Et = PC->varlist_end();
5279 llvm_unreachable(
"Expected private clause.");
5281 for (
Expr *
E : llvm::make_range(It, Et)) {
5288 Expr *SimpleRefExpr =
E;
5291 DeclToCopy.try_emplace(Res.first,
5292 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5297 auto *AC = cast<OMPAllocateClause>(
C);
5301 AC->getAllocator()) {
5302 Expr *Allocator = AC->getAllocator();
5308 AllocatorChecker Checker(Stack);
5309 if (Checker.Visit(Allocator))
5310 S.
Diag(Allocator->getExprLoc(),
5311 diag::err_omp_allocator_not_in_uses_allocators)
5312 << Allocator->getSourceRange();
5314 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5320 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5323 S.
Diag(AC->getAllocator()->getExprLoc(),
5324 diag::warn_omp_allocate_thread_on_task_target_directive)
5325 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5327 for (
Expr *
E : AC->varlist()) {
5330 Expr *SimpleRefExpr =
E;
5333 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5336 diag::err_omp_expected_private_copy_for_allocate);
5339 VarDecl *PrivateVD = DeclToCopy[VD];
5341 AllocatorKind, AC->getAllocator()))
5344 Expr *Alignment =
nullptr;
5361 CaptureVars(
Sema &Actions) : BaseTransform(Actions) {}
5363 bool AlwaysRebuild() {
return true; }
5376 BodyStmts.push_back(NewDeclStmt);
5414 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5425 auto BuildVarRef = [&](
VarDecl *VD) {
5430 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
5432 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5438 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5442 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5446 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5450 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5454 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5456 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5460 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5462 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5463 "Expected one of these relational operators");
5470 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5474 if (Rel == BO_GE || Rel == BO_GT)
5476 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5479 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5485 if (Rel == BO_LE || Rel == BO_GE) {
5497 Expr *Divisor = BuildVarRef(NewStep);
5498 if (Rel == BO_GE || Rel == BO_GT)
5501 Expr *DivisorMinusOne =
5506 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5516 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
5517 BodyStmts.push_back(ResultAssign);
5522 return cast<CapturedStmt>(
5549 {
"Logical", LogicalTy},
5560 assert(!
Invalid &&
"Expecting capture-by-value to work.");
5565 auto *CS = cast<CapturedDecl>(Actions.
CurContext);
5569 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5572 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
5575 CaptureVars Recap(Actions);
5580 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
5595 BO_Assign, TargetRef, Advanced));
5597 return cast<CapturedStmt>(
5608 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
5610 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
5612 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5613 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
5615 assert(LCAssign->getOpcode() == BO_Assign &&
5616 "init part must be a loop variable assignment");
5617 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5618 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5620 llvm_unreachable(
"Cannot determine loop variable");
5623 Cond = For->getCond();
5624 Inc = For->getInc();
5625 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5626 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5628 LUVDecl = RangeFor->getLoopVariable();
5630 Cond = RangeFor->getCond();
5631 Inc = RangeFor->getInc();
5633 llvm_unreachable(
"unhandled kind of loop");
5642 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5643 LHS = CondBinExpr->getLHS();
5644 RHS = CondBinExpr->getRHS();
5645 CondRel = CondBinExpr->getOpcode();
5646 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5647 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
5648 LHS = CondCXXOp->getArg(0);
5649 RHS = CondCXXOp->getArg(1);
5650 switch (CondCXXOp->getOperator()) {
5651 case OO_ExclaimEqual:
5663 case OO_GreaterEqual:
5667 llvm_unreachable(
"unexpected iterator operator");
5670 llvm_unreachable(
"unexpected loop condition");
5674 cast<DeclRefExpr>(LHS->
IgnoreImplicit())->getDecl() != LIVDecl) {
5675 std::swap(LHS, RHS);
5692 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5694 switch (IncUn->getOpcode()) {
5704 llvm_unreachable(
"unhandled unary increment operator");
5707 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction), LogicalTy, {});
5708 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5709 if (IncBin->getOpcode() == BO_AddAssign) {
5710 Step = IncBin->getRHS();
5711 }
else if (IncBin->getOpcode() == BO_SubAssign) {
5715 llvm_unreachable(
"unhandled binary increment operator");
5716 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5717 switch (CondCXXOp->getOperator()) {
5720 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
5724 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
5727 Step = CondCXXOp->getArg(1);
5734 llvm_unreachable(
"unhandled overloaded increment operator");
5737 llvm_unreachable(
"unknown increment expression");
5742 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5745 nullptr,
nullptr, {},
nullptr);
5747 LoopVarFunc, LVRef);
5752 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5759 "Loop transformation directive expected");
5760 return LoopTransform;
5767 Expr *UnresolvedMapper);
5779 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5780 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5784 auto *MI =
C->mapperlist_begin();
5785 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
5805 ElemType = ATy->getElementType();
5808 CanonType = ElemType;
5813 1, {CanonType,
nullptr});
5814 llvm::DenseMap<const Type *, Expr *>
Visited;
5817 while (!Types.empty()) {
5820 std::tie(BaseType, CurFD) = Types.pop_back_val();
5821 while (ParentChain.back().second == 0)
5822 ParentChain.pop_back();
5823 --ParentChain.back().second;
5839 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5850 Expr *BaseExpr = OE;
5851 for (
const auto &
P : ParentChain) {
5869 SubExprs.push_back(BaseExpr);
5873 bool FirstIter =
true;
5883 ParentChain.emplace_back(CurFD, 1);
5885 ++ParentChain.back().second;
5887 Types.emplace_back(FieldTy, FD);
5891 if (SubExprs.empty())
5896 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
5897 MapperIdScopeSpec, MapperId,
C->getMapType(),
5900 Clauses.push_back(NewClause);
5915 if (
D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5917 if (
C->getBindKind() == OMPC_BIND_parallel) {
5918 TeamsLoopCanBeParallelFor =
false;
5923 for (
const Stmt *Child :
D->children())
5933 bool IsOpenMPAPI =
false;
5934 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
5936 std::string Name = FD->getNameInfo().getAsString();
5937 IsOpenMPAPI = Name.find(
"omp_") == 0;
5939 TeamsLoopCanBeParallelFor =
5940 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5941 if (!TeamsLoopCanBeParallelFor)
5944 for (
const Stmt *Child :
C->children())
5952 Visit(S->getCapturedDecl()->getBody());
5955 void VisitStmt(
const Stmt *S) {
5958 for (
const Stmt *Child : S->children())
5962 explicit TeamsLoopChecker(
Sema &SemaRef)
5963 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
5966 bool TeamsLoopCanBeParallelFor;
5971 TeamsLoopChecker Checker(SemaRef);
5972 Checker.Visit(AStmt);
5973 return Checker.teamsLoopCanBeParallelFor();
5987 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5988 BindKind = BC->getBindKind();
6000 BindKind = OMPC_BIND_thread;
6002 getLeafConstructsOrSelf(ParentDirective);
6004 if (ParentDirective == OMPD_unknown) {
6006 diag::err_omp_bind_required_on_loop);
6007 }
else if (ParentLeafs.back() == OMPD_parallel) {
6008 BindKind = OMPC_BIND_parallel;
6009 }
else if (ParentLeafs.back() == OMPD_teams) {
6010 BindKind = OMPC_BIND_teams;
6018 ClausesWithImplicit.push_back(
C);
6022 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6024 if (
C->getClauseKind() == OMPC_reduction)
6026 diag::err_omp_loop_reduction_clause);
6033 BindKind, StartLoc)) {
6040 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6043 bool ErrorFound =
false;
6044 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6048 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
6051 DSAAttrChecker DSAChecker(
DSAStack,
SemaRef, cast<CapturedStmt>(AStmt));
6054 while (--ThisCaptureLevel >= 0)
6055 S = cast<CapturedStmt>(S)->getCapturedStmt();
6056 DSAChecker.Visit(S);
6060 auto *CS = cast<CapturedStmt>(AStmt);
6064 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6066 DSAChecker.visitSubCaptures(CS);
6068 if (DSAChecker.isErrorFound())
6071 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6074 DSAChecker.getImplicitFirstprivate());
6079 ImplicitMapModifiers[DefaultmapKindNum];
6081 ImplicitMapModifiersLoc[DefaultmapKindNum];
6085 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6086 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6087 PresentModifierLocs[DMC->getDefaultmapKind()] =
6088 DMC->getDefaultmapModifierLoc();
6090 for (
unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6092 for (
unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6095 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6098 DSAChecker.getImplicitMapModifier(K);
6099 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6100 ImplicitModifier.end());
6101 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6102 ImplicitModifier.size(), PresentModifierLocs[VC]);
6106 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6107 for (
Expr *
E : IRC->taskgroup_descriptors())
6109 ImplicitFirstprivates.emplace_back(
E);
6114 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6115 ImplicitFirstprivates.push_back(DC->getEventHandler());
6117 if (!ImplicitFirstprivates.empty()) {
6121 ClausesWithImplicit.push_back(
Implicit);
6122 ErrorFound = cast<OMPFirstprivateClause>(
Implicit)->varlist_size() !=
6123 ImplicitFirstprivates.size();
6128 if (!ImplicitPrivates.empty()) {
6132 ClausesWithImplicit.push_back(
Implicit);
6133 ErrorFound = cast<OMPPrivateClause>(
Implicit)->varlist_size() !=
6134 ImplicitPrivates.size();
6143 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6147 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6148 for (
Expr *
E : RC->varlist())
6150 ImplicitExprs.emplace_back(
E);
6152 if (!ImplicitExprs.empty()) {
6158 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6161 ClausesWithImplicit.emplace_back(
Implicit);
6164 for (
unsigned I = 0,
E = DefaultmapKindNum; I <
E; ++I) {
6165 int ClauseKindCnt = -1;
6168 if (ImplicitMap.empty())
6174 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6175 MapperIdScopeSpec, MapperId, K,
true,
6178 ClausesWithImplicit.emplace_back(
Implicit);
6179 ErrorFound |= cast<OMPMapClause>(
Implicit)->varlist_size() !=
6190 ClausesWithImplicit);
6200 VarsWithInheritedDSA);
6211 assert(ClausesWithImplicit.empty() &&
6212 "reverse directive does not support any clauses");
6215 case OMPD_interchange:
6221 VarsWithInheritedDSA);
6225 EndLoc, VarsWithInheritedDSA);
6232 assert(ClausesWithImplicit.empty() &&
6233 "No clauses are allowed for 'omp section' directive");
6241 assert(ClausesWithImplicit.empty() &&
6242 "No clauses are allowed for 'omp master' directive");
6253 case OMPD_parallel_for:
6255 EndLoc, VarsWithInheritedDSA);
6257 case OMPD_parallel_for_simd:
6259 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6265 case OMPD_parallel_master:
6269 case OMPD_parallel_masked:
6273 case OMPD_parallel_sections:
6281 case OMPD_taskyield:
6282 assert(ClausesWithImplicit.empty() &&
6283 "No clauses are allowed for 'omp taskyield' directive");
6284 assert(AStmt ==
nullptr &&
6285 "No associated statement allowed for 'omp taskyield' directive");
6289 assert(AStmt ==
nullptr &&
6290 "No associated statement allowed for 'omp error' directive");
6294 assert(ClausesWithImplicit.empty() &&
6295 "No clauses are allowed for 'omp barrier' directive");
6296 assert(AStmt ==
nullptr &&
6297 "No associated statement allowed for 'omp barrier' directive");
6301 assert(AStmt ==
nullptr &&
6302 "No associated statement allowed for 'omp taskwait' directive");
6305 case OMPD_taskgroup:
6310 assert(AStmt ==
nullptr &&
6311 "No associated statement allowed for 'omp flush' directive");
6315 assert(AStmt ==
nullptr &&
6316 "No associated statement allowed for 'omp depobj' directive");
6320 assert(AStmt ==
nullptr &&
6321 "No associated statement allowed for 'omp scan' directive");
6340 case OMPD_target_parallel:
6344 case OMPD_target_parallel_for:
6346 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6348 case OMPD_cancellation_point:
6349 assert(ClausesWithImplicit.empty() &&
6350 "No clauses are allowed for 'omp cancellation point' directive");
6351 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
6352 "cancellation point' directive");
6356 assert(AStmt ==
nullptr &&
6357 "No associated statement allowed for 'omp cancel' directive");
6361 case OMPD_target_data:
6365 case OMPD_target_enter_data:
6369 case OMPD_target_exit_data:
6375 EndLoc, VarsWithInheritedDSA);
6377 case OMPD_taskloop_simd:
6379 EndLoc, VarsWithInheritedDSA);
6381 case OMPD_master_taskloop:
6383 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6385 case OMPD_masked_taskloop:
6387 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6389 case OMPD_master_taskloop_simd:
6391 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6393 case OMPD_masked_taskloop_simd:
6395 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6397 case OMPD_parallel_master_taskloop:
6399 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6401 case OMPD_parallel_masked_taskloop:
6403 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6405 case OMPD_parallel_master_taskloop_simd:
6407 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6409 case OMPD_parallel_masked_taskloop_simd:
6411 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6413 case OMPD_distribute:
6415 EndLoc, VarsWithInheritedDSA);
6417 case OMPD_target_update:
6421 case OMPD_distribute_parallel_for:
6423 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6425 case OMPD_distribute_parallel_for_simd:
6427 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6429 case OMPD_distribute_simd:
6431 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6433 case OMPD_target_parallel_for_simd:
6435 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6437 case OMPD_target_simd:
6439 EndLoc, VarsWithInheritedDSA);
6441 case OMPD_teams_distribute:
6443 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6445 case OMPD_teams_distribute_simd:
6447 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6449 case OMPD_teams_distribute_parallel_for_simd:
6451 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6453 case OMPD_teams_distribute_parallel_for:
6455 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6457 case OMPD_target_teams:
6461 case OMPD_target_teams_distribute:
6463 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6465 case OMPD_target_teams_distribute_parallel_for:
6467 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6469 case OMPD_target_teams_distribute_parallel_for_simd:
6471 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6473 case OMPD_target_teams_distribute_simd:
6475 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6478 assert(AStmt ==
nullptr &&
6479 "No associated statement allowed for 'omp interop' directive");
6488 EndLoc, VarsWithInheritedDSA);
6490 case OMPD_teams_loop:
6492 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6494 case OMPD_target_teams_loop:
6496 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6498 case OMPD_parallel_loop:
6500 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6502 case OMPD_target_parallel_loop:
6504 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6506 case OMPD_declare_target:
6507 case OMPD_end_declare_target:
6508 case OMPD_threadprivate:
6510 case OMPD_declare_reduction:
6511 case OMPD_declare_mapper:
6512 case OMPD_declare_simd:
6514 case OMPD_declare_variant:
6515 case OMPD_begin_declare_variant:
6516 case OMPD_end_declare_variant:
6517 llvm_unreachable(
"OpenMP Directive is not allowed");
6520 llvm_unreachable(
"Unknown OpenMP directive");
6523 ErrorFound = Res.
isInvalid() || ErrorFound;
6527 if (
DSAStack->getDefaultDSA() == DSA_none ||
6528 DSAStack->getDefaultDSA() == DSA_private ||
6529 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6532 switch (
C->getClauseKind()) {
6533 case OMPC_num_threads:
6534 case OMPC_dist_schedule:
6541 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_target)
6545 cast<OMPIfClause>(
C)->getNameModifier() != OMPD_parallel)
6551 case OMPC_grainsize:
6552 case OMPC_num_tasks:
6555 case OMPC_novariants:
6556 case OMPC_nocontext:
6563 case OMPC_num_teams:
6564 case OMPC_thread_limit:
6571 case OMPC_proc_bind:
6573 case OMPC_firstprivate:
6574 case OMPC_lastprivate:
6576 case OMPC_reduction:
6577 case OMPC_task_reduction:
6578 case OMPC_in_reduction:
6582 case OMPC_copyprivate:
6585 case OMPC_mergeable:
6602 case OMPC_defaultmap:
6605 case OMPC_use_device_ptr:
6606 case OMPC_use_device_addr:
6607 case OMPC_is_device_ptr:
6608 case OMPC_has_device_addr:
6609 case OMPC_nontemporal:
6612 case OMPC_inclusive:
6613 case OMPC_exclusive:
6614 case OMPC_uses_allocators:
6619 case OMPC_allocator:
6622 case OMPC_threadprivate:
6625 case OMPC_unified_address:
6626 case OMPC_unified_shared_memory:
6627 case OMPC_reverse_offload:
6628 case OMPC_dynamic_allocators:
6629 case OMPC_atomic_default_mem_order:
6630 case OMPC_device_type:
6637 llvm_unreachable(
"Unexpected clause");
6639 for (
Stmt *CC :
C->children()) {
6641 DSAChecker.Visit(CC);
6644 for (
const auto &
P : DSAChecker.getVarsWithInheritedDSA())
6645 VarsWithInheritedDSA[
P.getFirst()] =
P.getSecond();
6647 for (
const auto &
P : VarsWithInheritedDSA) {
6648 if (
P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(
P.getFirst()))
6651 if (
DSAStack->getDefaultDSA() == DSA_none ||
6652 DSAStack->getDefaultDSA() == DSA_private ||
6653 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6654 Diag(
P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6655 <<
P.first <<
P.second->getSourceRange();
6656 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6658 Diag(
P.second->getExprLoc(),
6659 diag::err_omp_defaultmap_no_attr_for_variable)
6660 <<
P.first <<
P.second->getSourceRange();
6662 diag::note_omp_defaultmap_attr_none);
6668 if (isAllowedClauseForDirective(
D, OMPC_if,
getLangOpts().OpenMP))
6669 AllowedNameModifiers.push_back(
D);
6671 if (!AllowedNameModifiers.empty())
6685 DSAStack->addTargetDirLocation(StartLoc);
6696 assert(Aligneds.size() == Alignments.size());
6697 assert(Linears.size() == LinModifiers.size());
6698 assert(Linears.size() == Steps.size());
6699 if (!DG || DG.
get().isNull())
6702 const int SimdId = 0;
6703 if (!DG.
get().isSingleDecl()) {
6704 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6708 Decl *ADecl = DG.
get().getSingleDecl();
6709 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6710 ADecl = FTD->getTemplatedDecl();
6712 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6714 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
6730 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6731 const Expr *UniformedLinearThis =
nullptr;
6732 for (
const Expr *
E : Uniforms) {
6734 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6735 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6736 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6737 FD->getParamDecl(PVD->getFunctionScopeIndex())
6739 UniformedArgs.try_emplace(PVD->getCanonicalDecl(),
E);
6742 if (isa<CXXThisExpr>(
E)) {
6743 UniformedLinearThis =
E;
6747 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6757 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6758 const Expr *AlignedThis =
nullptr;
6759 for (
const Expr *
E : Aligneds) {
6761 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6762 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6764 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6765 FD->getParamDecl(PVD->getFunctionScopeIndex())
6769 if (AlignedArgs.count(CanonPVD) > 0) {
6771 << 1 << getOpenMPClauseName(OMPC_aligned)
6773 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6774 diag::note_omp_explicit_dsa)
6775 << getOpenMPClauseName(OMPC_aligned);
6778 AlignedArgs[CanonPVD] =
E;
6780 .getNonReferenceType()
6781 .getUnqualifiedType()
6782 .getCanonicalType();
6787 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6792 if (isa<CXXThisExpr>(
E)) {
6797 << getOpenMPClauseName(OMPC_aligned);
6803 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6810 for (
Expr *
E : Alignments) {
6814 NewAligns.push_back(Align.
get());
6825 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6826 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
6827 auto MI = LinModifiers.begin();
6828 for (
const Expr *
E : Linears) {
6832 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E))
6833 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6835 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6836 FD->getParamDecl(PVD->getFunctionScopeIndex())
6840 if (LinearArgs.count(CanonPVD) > 0) {
6842 << getOpenMPClauseName(OMPC_linear)
6844 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6845 diag::note_omp_explicit_dsa)
6846 << getOpenMPClauseName(OMPC_linear);
6850 if (UniformedArgs.count(CanonPVD) > 0) {
6852 << getOpenMPClauseName(OMPC_linear)
6854 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6855 diag::note_omp_explicit_dsa)
6856 << getOpenMPClauseName(OMPC_uniform);
6859 LinearArgs[CanonPVD] =
E;
6865 PVD->getOriginalType(),
6870 if (isa<CXXThisExpr>(
E)) {
6871 if (UniformedLinearThis) {
6873 << getOpenMPClauseName(OMPC_linear)
6874 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6876 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
6877 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6881 UniformedLinearThis =
E;
6890 << FD->
getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6892 Expr *Step =
nullptr;
6893 Expr *NewStep =
nullptr;
6895 for (
Expr *
E : Steps) {
6897 if (Step ==
E || !
E) {
6898 NewSteps.push_back(
E ? NewStep :
nullptr);
6902 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6903 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6905 if (UniformedArgs.count(CanonPVD) == 0) {
6912 NewSteps.push_back(Step);
6931 NewSteps.push_back(NewStep);
6933 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6935 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
6936 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
6937 const_cast<Expr **
>(Linears.data()), Linears.size(),
6938 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
6939 NewSteps.data(), NewSteps.size(), SR);
6949 "Unexpected directive category");
6958 llvm_unreachable(
"Unknown OpenMP directive");
6967 "Expected function type with prototype.");
6969 "Expected function with type with no prototype.");
6971 "Expected function with prototype.");
6979 Param->setScopeInfo(0, Params.size());
6980 Param->setImplicit();
6981 Params.push_back(Param);
6984 FD->setParams(Params);
6991 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
6992 FD = UTemplDecl->getTemplatedDecl();
6994 FD = cast<FunctionDecl>(
D);
6995 assert(FD &&
"Expected a function declaration!");
7001 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7004 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7008SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7009 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7014 if (!
D.getIdentifier())
7017 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7020 bool IsTemplated = !TemplateParamLists.empty();
7022 !DVScope.TI->isExtensionActive(
7023 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7040 for (
auto *Candidate : Lookup) {
7041 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7043 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7044 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7045 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7046 UDecl = FTD->getTemplatedDecl();
7047 }
else if (!IsTemplated)
7048 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7062 FType, UDeclTy,
false,
7069 Bases.push_back(UDecl);
7072 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7073 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7075 if (Bases.empty() && UseImplicitBase) {
7079 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7080 Bases.push_back(BaseTemplD->getTemplatedDecl());
7082 Bases.push_back(cast<FunctionDecl>(BaseD));
7085 std::string MangledName;
7086 MangledName +=
D.getIdentifier()->getName();
7088 MangledName += DVScope.NameSuffix;
7103 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(
D))
7104 FD = UTemplDecl->getTemplatedDecl();
7106 FD = cast<FunctionDecl>(
D);
7113 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7114 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7120 BaseFD->addAttr(OMPDeclareVariantA);
7139 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7142 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7145 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7149 std::function<void(StringRef)> DiagUnknownTrait = [
this,
7150 CE](StringRef ISATrait) {
7164 while (CalleeFnDecl) {
7165 for (OMPDeclareVariantAttr *A :
7167 Expr *VariantRef = A->getVariantFuncRef();
7169 VariantMatchInfo VMI;
7172 if (!isVariantApplicableInContext(VMI, OMPCtx,
7176 VMIs.push_back(VMI);
7177 Exprs.push_back(VariantRef);
7185 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7188 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7189 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7205 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7206 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7208 Context, MemberCall->getImplicitObjectArgument(),
7210 MemberCall->getValueKind(), MemberCall->getObjectKind());
7213 RParenLoc, ExecConfig);
7215 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7216 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7218 CalleeFnType, NewCalleeFnDecl->
getType(),
7229 VMIs.erase(VMIs.begin() + BestIdx);
7230 Exprs.erase(Exprs.begin() + BestIdx);
7231 }
while (!VMIs.empty());
7238std::optional<std::pair<FunctionDecl *, Expr *>>
7242 unsigned NumAppendArgs,
7245 if (!DG || DG.
get().isNull())
7246 return std::nullopt;
7248 const int VariantId = 1;
7250 if (!DG.
get().isSingleDecl()) {
7251 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7253 return std::nullopt;
7255 Decl *ADecl = DG.
get().getSingleDecl();
7256 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7257 ADecl = FTD->getTemplatedDecl();
7260 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7264 return std::nullopt;
7267 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
7270 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
7273 if (HasMultiVersionAttributes(FD)) {
7274 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7276 return std::nullopt;
7281 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
7286 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
7288 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
7293 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
7294 return std::nullopt;
7297 auto ShouldDelayChecks = [](
Expr *&
E,
bool) {
7303 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
7305 return std::make_pair(FD, VariantRef);
7308 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&
E,
7309 bool IsScore) ->
bool {
7315 Diag(
E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7323 diag::err_omp_declare_variant_user_condition_not_constant)
7329 return std::nullopt;
7332 if (NumAppendArgs) {
7335 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
7337 return std::nullopt;
7346 TD = dyn_cast_or_null<TypeDecl>(ND);
7349 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
7350 return std::nullopt;
7353 if (PTy->isVariadic()) {
7354 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7355 return std::nullopt;
7358 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7359 Params.insert(Params.end(), NumAppendArgs, InteropType);
7360 AdjustedFnType = Context.
getFunctionType(PTy->getReturnType(), Params,
7361 PTy->getExtProtoInfo());
7369 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7370 if (Method && !Method->isStatic()) {
7371 const Type *ClassType =
7385 return std::nullopt;
7387 VariantRef = ER.
get();
7395 false, Sema::AllowedExplicit::None,
7401 diag::err_omp_declare_variant_incompat_types)
7403 << ((Method && !Method->isStatic()) ? FnPtrType : FD->
getType())
7405 return std::nullopt;
7410 return std::nullopt;
7413 if (Method && !Method->isStatic()) {
7414 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
7415 if (
auto *UO = dyn_cast<UnaryOperator>(
7417 VariantRefCast = UO->getSubExpr();
7426 return std::nullopt;
7434 return std::nullopt;
7436 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7440 return std::nullopt;
7445 diag::err_omp_declare_variant_same_base_function)
7447 return std::nullopt;
7456 diag::err_omp_declare_variant_incompat_types)
7457 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
7459 return std::nullopt;
7464 else if (NewFD->getType()->isFunctionNoProtoType())
7470 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7472 diag::warn_omp_declare_variant_marked_as_declare_variant)
7475 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
7476 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7477 return std::nullopt;
7480 enum DoesntSupport {
7489 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7490 if (CXXFD->isVirtual()) {
7493 return std::nullopt;
7496 if (isa<CXXConstructorDecl>(FD)) {
7499 return std::nullopt;
7502 if (isa<CXXDestructorDecl>(FD)) {
7505 return std::nullopt;
7509 if (FD->isDeleted()) {
7512 return std::nullopt;
7515 if (FD->isDefaulted()) {
7518 return std::nullopt;
7521 if (FD->isConstexpr()) {
7523 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7524 return std::nullopt;
7534 SemaRef.
PDiag(diag::err_omp_declare_variant_doesnt_support)),
7540 return std::nullopt;
7541 return std::make_pair(FD, cast<Expr>(DRE));
7557 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7558 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7560 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7561 VariantMatchInfo VMI;
7563 if (!llvm::is_contained(
7564 VMI.ConstructTraits,
7565 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7566 if (!AllAdjustArgs.empty())
7567 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7568 << getOpenMPClauseName(OMPC_adjust_args);
7569 if (!AppendArgs.empty())
7570 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7571 << getOpenMPClauseName(OMPC_append_args);
7581 for (
Expr *
E : AllAdjustArgs) {
7583 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
E)) {
7584 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7586 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
7590 if (!AdjustVars.insert(CanonPVD).second) {
7591 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7600 Diag(
E->
getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7604 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7606 const_cast<Expr **
>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7607 const_cast<Expr **
>(AdjustArgsNeedDevicePtr.data()),
7608 AdjustArgsNeedDevicePtr.size(),
7609 const_cast<OMPInteropInfo *
>(AppendArgs.data()), AppendArgs.size(), SR);
7615 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7616 assert(CS &&
"Captured statement expected");
7625 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7654struct LoopIterationSpace final {
7657 bool IsStrictCompare =
false;
7659 Expr *PreCond =
nullptr;
7662 Expr *NumIterations =
nullptr;
7664 Expr *CounterVar =
nullptr;
7666 Expr *PrivateCounterVar =
nullptr;
7668 Expr *CounterInit =
nullptr;
7671 Expr *CounterStep =
nullptr;
7673 bool Subtract =
false;
7683 Expr *MinValue =
nullptr;
7687 Expr *MaxValue =
nullptr;
7689 bool IsNonRectangularLB =
false;
7691 bool IsNonRectangularUB =
false;
7694 unsigned LoopDependentIdx = 0;
7698 Expr *FinalCondition =
nullptr;
7704class OpenMPIterationSpaceChecker {
7708 bool SupportsNonRectangular;
7724 Expr *LCRef =
nullptr;
7730 Expr *Step =
nullptr;
7737 std::optional<bool> TestIsLessOp;
7739 bool TestIsStrictOp =
false;
7741 bool SubtractStep =
false;
7746 std::optional<unsigned> InitDependOnLC;
7749 std::optional<unsigned> CondDependOnLC;
7751 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
7752 bool IsInitializer);
7758 OpenMPIterationSpaceChecker(
Sema &SemaRef,
bool SupportsNonRectangular,
7760 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7761 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7764 bool checkAndSetInit(
Stmt *S,
bool EmitDiags =
true);
7767 bool checkAndSetCond(
Expr *S);
7770 bool checkAndSetInc(
Expr *S);
7772 ValueDecl *getLoopDecl()
const {
return LCDecl; }
7774 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
7776 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
7778 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
7780 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
7782 bool shouldSubtractStep()
const {
return SubtractStep; }
7784 bool isStrictTestOp()
const {
return TestIsStrictOp; }
7786 Expr *buildNumIterations(
7788 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7792 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7795 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7796 DSAStackTy &DSA)
const;
7799 Expr *buildPrivateCounterVar()
const;
7803 Expr *buildCounterStep()
const;
7807 buildOrderedLoopData(
Scope *S,
Expr *Counter,
7808 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7812 std::pair<Expr *, Expr *> buildMinMaxValues(
7813 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
7815 Expr *buildFinalCondition(
Scope *S)
const;
7817 bool dependent()
const;
7819 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
7821 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
7823 unsigned getLoopDependentIdx()
const {
7824 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7830 bool checkAndSetIncRHS(
Expr *RHS);
7835 bool setUB(
Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
7838 bool setStep(
Expr *NewStep,
bool Subtract);
7841bool OpenMPIterationSpaceChecker::dependent()
const {
7843 assert(!LB && !UB && !Step);
7851bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
7853 Expr *NewLB,
bool EmitDiags) {
7855 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
7856 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7860 LCRef = NewLCRefExpr;
7861 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7863 if ((Ctor->isCopyOrMoveConstructor() ||
7864 Ctor->isConvertingConstructor(
false)) &&
7865 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
7869 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
7873bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
7877 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
7878 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
7883 TestIsLessOp = LessOp;
7884 TestIsStrictOp = StrictOp;
7885 ConditionSrcRange = SR;
7887 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
7891bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
7893 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
7903 NewStep = Val.
get();
7916 std::optional<llvm::APSInt>
Result =
7927 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7928 if (UB && (IsConstZero ||
7929 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7930 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7932 diag::err_omp_loop_incr_not_compatible)
7934 SemaRef.
Diag(ConditionLoc,
7935 diag::note_omp_loop_cond_requires_compatible_incr)
7936 << *TestIsLessOp << ConditionSrcRange;
7939 if (*TestIsLessOp == Subtract) {
7943 Subtract = !Subtract;
7948 SubtractStep = Subtract;
7955class LoopCounterRefChecker final
7962 bool IsInitializer =
true;
7963 bool SupportsNonRectangular;
7964 unsigned BaseLoopId = 0;
7967 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7968 << (IsInitializer ? 0 : 1);
7971 const auto &&
Data = Stack.isLoopControlVariable(VD);
7977 llvm::raw_svector_ostream OS(Name);
7981 diag::err_omp_wrong_dependency_iterator_type)
7983 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
7986 if (
Data.first && !SupportsNonRectangular) {
7987 SemaRef.Diag(
E->
getExprLoc(), diag::err_omp_invariant_dependency);
7991 (DepDecl || (PrevDepDecl &&
7993 if (!DepDecl && PrevDepDecl)
7994 DepDecl = PrevDepDecl;
7996 llvm::raw_svector_ostream OS(Name);
8000 diag::err_omp_invariant_or_linear_dependency)
8006 BaseLoopId =
Data.first;
8014 if (isa<VarDecl>(VD))
8015 return checkDecl(
E, VD);
8021 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8022 return checkDecl(
E, VD);
8026 bool VisitStmt(
const Stmt *S) {
8028 for (
const Stmt *Child : S->children())
8029 Res = (Child && Visit(Child)) || Res;
8032 explicit LoopCounterRefChecker(
Sema &SemaRef, DSAStackTy &Stack,
8033 const ValueDecl *CurLCDecl,
bool IsInitializer,
8035 bool SupportsNonRectangular =
true)
8036 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8037 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8038 SupportsNonRectangular(SupportsNonRectangular) {}
8039 unsigned getBaseLoopId()
const {
8040 assert(CurLCDecl &&
"Expected loop dependency.");
8044 assert(CurLCDecl &&
"Expected loop dependency.");
8050std::optional<unsigned>
8051OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
8052 bool IsInitializer) {
8054 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8055 DepDecl, SupportsNonRectangular);
8056 if (LoopStmtChecker.Visit(S)) {
8057 DepDecl = LoopStmtChecker.getDepDecl();
8058 return LoopStmtChecker.getBaseLoopId();
8060 return std::nullopt;
8063bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
8074 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8078 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8079 if (!ExprTemp->cleanupsHaveSideEffects())
8080 S = ExprTemp->getSubExpr();
8082 InitSrcRange = S->getSourceRange();
8083 if (
Expr *
E = dyn_cast<Expr>(S))
8085 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8086 if (BO->getOpcode() == BO_Assign) {
8088 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8089 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8091 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8093 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8095 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8096 if (ME->isArrow() &&
8097 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8098 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8102 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
8103 if (DS->isSingleDecl()) {
8104 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8105 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8108 SemaRef.Diag(S->getBeginLoc(),
8109 diag::ext_omp_loop_not_canonical_init)
8110 << S->getSourceRange();
8111 return setLCDeclAndLB(
8114 Var->getType().getNonReferenceType(),
8116 Var->getInit(), EmitDiags);
8120 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8121 if (CE->getOperator() == OO_Equal) {
8122 Expr *LHS = CE->getArg(0);
8123 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8124 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8126 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8128 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8130 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
8131 if (ME->isArrow() &&
8132 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8133 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8139 if (dependent() || SemaRef.CurContext->isDependentContext())
8142 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8143 << S->getSourceRange();
8154 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(
E))
8156 if ((Ctor->isCopyOrMoveConstructor() ||
8157 Ctor->isConvertingConstructor(
false)) &&
8158 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8160 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(
E)) {
8161 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8164 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(
E))
8165 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8170bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
8177 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8179 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8180 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8186 auto &&CheckAndSetCond =
8191 if (getInitLCDecl(LHS) == LCDecl)
8192 return setUB(
const_cast<Expr *
>(RHS),
8194 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8195 if (getInitLCDecl(RHS) == LCDecl)
8196 return setUB(
const_cast<Expr *
>(LHS),
8198 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8199 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
8200 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8204 return std::nullopt;
8206 std::optional<bool> Res;
8207 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8210 RBO->getOperatorLoc());
8211 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8212 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8213 BO->getSourceRange(), BO->getOperatorLoc());
8214 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8215 if (CE->getNumArgs() == 2) {
8216 Res = CheckAndSetCond(
8218 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8223 if (dependent() || SemaRef.CurContext->isDependentContext())
8225 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8226 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8230bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
8237 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8238 if (BO->isAdditiveOp()) {
8239 bool IsAdd = BO->getOpcode() == BO_Add;
8240 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8241 return setStep(BO->getRHS(), !IsAdd);
8242 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8243 return setStep(BO->getLHS(),
false);
8245 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8246 bool IsAdd = CE->getOperator() == OO_Plus;
8247 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8248 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8249 return setStep(CE->getArg(1), !IsAdd);
8250 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8251 return setStep(CE->getArg(0),
false);
8254 if (dependent() || SemaRef.CurContext->isDependentContext())
8256 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8261bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
8276 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8279 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8280 if (!ExprTemp->cleanupsHaveSideEffects())
8281 S = ExprTemp->getSubExpr();
8283 IncrementSrcRange = S->getSourceRange();
8284 S = S->IgnoreParens();
8285 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
8286 if (UO->isIncrementDecrementOp() &&
8287 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8288 return setStep(SemaRef
8289 .ActOnIntegerConstant(UO->getBeginLoc(),
8290 (UO->isDecrementOp() ? -1 : 1))
8293 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
8294 switch (BO->getOpcode()) {
8297 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8298 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8301 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8302 return checkAndSetIncRHS(BO->getRHS());
8307 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8308 switch (CE->getOperator()) {
8311 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8312 return setStep(SemaRef
8313 .ActOnIntegerConstant(
8315 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8321 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8322 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8325 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8326 return checkAndSetIncRHS(CE->getArg(1));
8332 if (dependent() || SemaRef.CurContext->isDependentContext())
8334 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8335 << S->getSourceRange() << LCDecl;
8341 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8342 StringRef Name =
".capture_expr.") {
8349 auto I = Captures.find(
Capture);
8350 if (I != Captures.end())
8363 bool TestIsStrictOp,
bool RoundToStep,
8364 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8365 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8368 llvm::APSInt LRes, SRes;
8369 bool IsLowerConst =
false, IsStepConst =
false;
8370 if (std::optional<llvm::APSInt> Res =
8373 IsLowerConst =
true;
8375 if (std::optional<llvm::APSInt> Res =
8380 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8381 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8382 (TestIsStrictOp && LRes.isStrictlyPositive()));
8383 bool NeedToReorganize =
false;
8385 if (!NoNeedToConvert && IsLowerConst &&
8386 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8387 NoNeedToConvert =
true;
8389 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8390 ? LRes.getBitWidth()
8391 : SRes.getBitWidth();
8392 LRes = LRes.extend(BW + 1);
8393 LRes.setIsSigned(
true);
8394 SRes = SRes.extend(BW + 1);
8395 SRes.setIsSigned(
true);
8397 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8398 LRes = LRes.trunc(BW);
8400 if (TestIsStrictOp) {
8401 unsigned BW = LRes.getBitWidth();
8402 LRes = LRes.extend(BW + 1);
8403 LRes.setIsSigned(
true);
8406 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8408 LRes = LRes.trunc(BW);
8410 NeedToReorganize = NoNeedToConvert;
8413 bool IsUpperConst =
false;
8414 if (std::optional<llvm::APSInt> Res =
8417 IsUpperConst =
true;
8419 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8420 (!RoundToStep || IsStepConst)) {
8421 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8422 : URes.getBitWidth();
8423 LRes = LRes.extend(BW + 1);
8424 LRes.setIsSigned(
true);
8425 URes = URes.extend(BW + 1);
8426 URes.setIsSigned(
true);
8428 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8429 NeedToReorganize = NoNeedToConvert;
8434 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8440 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8443 LowerSize > UpperSize ? LowerSize : UpperSize, 0);
8454 if (!Lower || !Upper || NewStep.
isInvalid())
8460 if (NeedToReorganize) {
8474 S, DefaultLoc, BO_Add, Diff.
get(),
8484 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
8488 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8504 S, DefaultLoc, BO_Sub, Diff.
get(),
8524 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
8532Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8534 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8543 if (InitDependOnLC) {
8544 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8545 if (!IS.MinValue || !IS.MaxValue)
8554 IS.CounterVar, MinValue.
get());
8559 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
8574 IS.CounterVar, MaxValue.
get());
8579 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
8588 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
8590 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
8591 if (!LBMin || !LBMax)
8595 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8599 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
8603 if (*TestIsLessOp) {
8607 MinLessMax, LBMin, LBMax);
8610 LBVal = MinLB.
get();
8615 MinLessMax, LBMax, LBMin);
8618 LBVal = MaxLB.
get();
8622 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8625 LBVal = LBMinVal.
get();
8629 if (CondDependOnLC) {
8630 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8631 if (!IS.MinValue || !IS.MaxValue)
8640 IS.CounterVar, MinValue.
get());
8645 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
8660 IS.CounterVar, MaxValue.
get());
8665 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
8674 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
8676 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
8677 if (!UBMin || !UBMax)
8681 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8684 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
8685 Captures,
".min_greater_max")
8689 if (*TestIsLessOp) {
8693 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8696 UBVal = MaxUB.
get();
8701 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8704 UBVal = MinUB.
get();
8707 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8708 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8709 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
8710 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
8711 if (!Upper || !Lower)
8714 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8715 Step, VarType, TestIsStrictOp,
8724 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
8727 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
8730 Type =
C.getIntTypeForBitwidth(NewSize, IsSigned);
8739 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
8740 if (NewSize !=
C.getTypeSize(
Type)) {
8741 if (NewSize <
C.getTypeSize(
Type)) {
8742 assert(NewSize == 64 &&
"incorrect loop var size");
8743 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8744 << InitSrcRange << ConditionSrcRange;
8746 QualType NewType =
C.getIntTypeForBitwidth(
8748 C.getTypeSize(
Type) < NewSize);
8761std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8762 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8766 return std::make_pair(
nullptr,
nullptr);
8769 Expr *MinExpr =
nullptr;
8770 Expr *MaxExpr =
nullptr;
8771 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8772 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8774 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8776 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8778 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8780 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8781 if (!Upper || !Lower)
8782 return std::make_pair(
nullptr,
nullptr);
8792 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8793 Step, VarType, TestIsStrictOp,
8796 return std::make_pair(
nullptr,
nullptr);
8802 return std::make_pair(
nullptr,
nullptr);
8804 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
8806 return std::make_pair(
nullptr,
nullptr);
8807 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
8809 return std::make_pair(
nullptr,
nullptr);
8814 return std::make_pair(
nullptr,
nullptr);
8826 return std::make_pair(
nullptr,
nullptr);
8828 if (*TestIsLessOp) {
8832 S, DefaultLoc, BO_Add,
8836 return std::make_pair(
nullptr,
nullptr);
8841 S, DefaultLoc, BO_Sub,
8845 return std::make_pair(
nullptr,
nullptr);
8854 return std::make_pair(
nullptr,
nullptr);
8859 return std::make_pair(
nullptr,
nullptr);
8862 MaxExpr = Diff.
get();
8864 MinExpr = Diff.
get();
8866 return std::make_pair(MinExpr, MaxExpr);
8869Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
8870 if (InitDependOnLC || CondDependOnLC)
8875Expr *OpenMPIterationSpaceChecker::buildPreCond(
8877 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
8882 if (CondDependOnLC || InitDependOnLC)
8893 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8894 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8900 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8901 : (TestIsStrictOp ? BO_GT : BO_GE),
8902 NewLB.
get(), NewUB.
get());
8912 return CondExpr.
isUsable() ? CondExpr.
get() : Cond;
8916DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8917 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8918 DSAStackTy &DSA)
const {
8919 auto *VD = dyn_cast<VarDecl>(LCDecl);
8924 const DSAStackTy::DSAVarData
Data =
8925 DSA.getTopDSA(LCDecl,
false);
8929 Captures.insert(std::make_pair(LCRef, Ref));
8932 return cast<DeclRefExpr>(LCRef);
8935Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
8941 isa<VarDecl>(LCDecl)
8952Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
8955Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
8957Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
8965 assert((OOK == OO_Plus || OOK == OO_Minus) &&
8966 "Expected only + or - operations for depend clauses.");
8978 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
8980 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
8981 if (!Upper || !Lower)
8985 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
8986 false,
false, Captures);
8996 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
8997 assert(
Init &&
"Expected loop in canonical form.");
8998 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
9004 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
9006 if (!ISC.checkAndSetInit(
Init,
false)) {
9008 auto *VD = dyn_cast<VarDecl>(
D);
9016 VD = cast<VarDecl>(PrivateRef->
getDecl());
9019 DSAStack->addLoopControlVariable(
D, VD);
9022 DSAStack->resetPossibleLoopCounter();
9023 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
9036 DSAStackTy::DSAVarData DVar =
9040 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9043 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9046 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9049 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9051 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9053 IsOpenMPTaskloopDirective(DKind) ||
9056 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9057 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9058 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9059 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9060 << getOpenMPClauseName(PredeterminedCKind);
9061 if (DVar.RefExpr ==
nullptr)
9062 DVar.CKind = PredeterminedCKind;
9064 }
else if (LoopDeclRefExpr) {
9069 if (DVar.CKind == OMPC_unknown)
9070 DSAStack->addDSA(
D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9074 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9079class OMPDoacrossKind {
9082 return C->getDependenceType() == OMPC_DOACROSS_source ||
9083 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9086 return C->getDependenceType() == OMPC_DOACROSS_sink;
9089 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9097 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
9098 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
9099 Expr *OrderedLoopCountExpr,
9102 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9107 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9108 S = CanonLoop->getLoopStmt();
9109 auto *For = dyn_cast_or_null<ForStmt>(S);
9110 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9112 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
9113 SemaRef.
Diag(S->getBeginLoc(), diag::err_omp_not_for)
9114 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
9115 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9116 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9117 if (TotalNestedLoopCount > 1) {
9118 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9119 SemaRef.
Diag(DSA.getConstructLoc(),
9120 diag::note_omp_collapse_ordered_expr)
9123 else if (CollapseLoopCountExpr)
9125 diag::note_omp_collapse_ordered_expr)
9129 diag::note_omp_collapse_ordered_expr)
9134 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9140 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9141 For ? For->getForLoc() : CXXFor->getForLoc());
9144 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
9145 if (ISC.checkAndSetInit(
Init))
9148 bool HasErrors =
false;
9151 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
9161 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9175 VarsWithImplicitDSA.erase(LCDecl);
9180 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9183 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9190 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9191 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9192 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9193 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9200 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9201 ISC.buildCounterVar(Captures, DSA);
9202 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9203 ISC.buildPrivateCounterVar();
9204 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9205 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9206 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9207 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9208 ISC.getConditionSrcRange();
9209 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9210 ISC.getIncrementSrcRange();
9211 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9212 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9213 ISC.isStrictTestOp();
9214 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9215 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9216 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9217 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9218 ISC.buildFinalCondition(DSA.getCurScope());
9219 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9220 ISC.doesInitDependOnLC();
9221 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9222 ISC.doesCondDependOnLC();
9223 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9224 ISC.getLoopDependentIdx();
9227 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
9228 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
9229 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
9230 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
9231 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
9232 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
9233 if (!HasErrors && DSA.isOrderedRegion()) {
9234 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9235 if (CurrentNestedLoopCount <
9236 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9237 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9238 CurrentNestedLoopCount,
9239 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9240 DSA.getOrderedRegionParam().second->setLoopCounter(
9241 CurrentNestedLoopCount,
9242 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9245 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
9246 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9247 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9249 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9250 if (CurrentNestedLoopCount >= NumLoops) {
9254 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9255 Pair.second.size() <= CurrentNestedLoopCount) {
9257 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
9260 OMPDoacrossKind ODK;
9261 if (DoacrossC && ODK.isSink(DoacrossC) &&
9262 Pair.second.size() <= CurrentNestedLoopCount) {
9264 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
9269 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9270 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9271 (DoacrossC && ODK.isSource(DoacrossC)))
9272 CntValue = ISC.buildOrderedLoopData(
9274 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9276 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9279 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9287 CntValue = ISC.buildOrderedLoopData(
9289 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9290 DepLoc, Inc, clang::OO_Minus);
9292 CntValue = ISC.buildOrderedLoopData(
9294 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9295 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9296 Pair.second[CurrentNestedLoopCount].second);
9298 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9300 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9311 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9315 : tryBuildCapture(SemaRef, Start.
get(), Captures);
9336 bool IsNonRectangularLB,
9337 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
9346 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
9361 if (Captures && !IsNonRectangularLB)
9362 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
9371 Update.get()->getType()->isOverloadableType()) {
9378 SemaRef.
BuildBinOp(S,
Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9379 VarRef.
get(), SavedUpdate.
get());
9390 NewStart.
get(), SavedUpdate.
get());
9414 unsigned HasBits =
C.getTypeSize(OldType);
9415 if (HasBits >= Bits)
9418 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
9428 if (std::optional<llvm::APSInt>
Result =
9437 if (!PreInits.empty()) {
9458 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
9467 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9468 if (!Captures.empty()) {
9470 for (
const auto &Pair : Captures)
9471 PreInits.push_back(Pair.second->getDecl());
9479 if (PreInits.empty())
9483 for (
Stmt *S : PreInits)
9490 Expr *PostUpdate =
nullptr;
9491 if (!PostUpdates.empty()) {
9492 for (
Expr *
E : PostUpdates) {
9498 PostUpdate = PostUpdate
9513 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
9517 unsigned NestedLoopCount = 1;
9518 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
9521 if (CollapseLoopCountExpr) {
9526 NestedLoopCount =
Result.Val.getInt().getLimitedValue();
9532 unsigned OrderedLoopCount = 1;
9533 if (OrderedLoopCountExpr) {
9540 if (
Result.getLimitedValue() < NestedLoopCount) {
9542 diag::err_omp_wrong_ordered_loop_count)
9545 diag::note_collapse_loop_count)
9548 OrderedLoopCount =
Result.getLimitedValue();
9556 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9557 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9561 SupportsNonPerfectlyNested, NumLoops,
9562 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9563 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9564 &IterSpaces, &Captures](
unsigned Cnt,
Stmt *CurStmt) {
9566 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9567 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9568 VarsWithImplicitDSA, IterSpaces, Captures))
9570 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9571 IterSpaces[Cnt].CounterVar) {
9573 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9574 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9575 Captures[DRE] = DRE;
9581 Stmt *DependentPreInits = Transform->getPreInits();
9582 if (!DependentPreInits)
9589 for (
Stmt *S : Constituents) {
9590 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
9591 for (
Decl *
C : DC->decls()) {
9592 auto *
D = cast<VarDecl>(
C);
9594 SemaRef,
D,
D->getType().getNonReferenceType(),
9596 Captures[Ref] = Ref;
9603 Built.
clear( NestedLoopCount);
9606 return NestedLoopCount;
9639 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
9640 Expr *N0 = IterSpaces[0].NumIterations;
9644 .PerformImplicitConversion(
9659 return NestedLoopCount;
9662 bool AllCountsNeedLessThan32Bits =
C.getTypeSize(N0->
getType()) < 32;
9664 Scope *CurScope = DSA.getCurScope();
9665 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9666 if (PreCond.isUsable()) {
9668 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9669 PreCond.get(), IterSpaces[Cnt].PreCond);
9671 Expr *N = IterSpaces[Cnt].NumIterations;
9673 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
9676 CurScope,
Loc, BO_Mul, LastIteration32.
get(),
9684 CurScope,
Loc, BO_Mul, LastIteration64.
get(),
9694 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
9696 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
9697 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9701 LastIteration64.
get(), SemaRef))))
9702 LastIteration = LastIteration32;
9721 LastIteration.
get(),
9733 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
9734 LastIteration = SaveRef;
9747 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9776 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
9785 UB.
get(), LastIteration.
get());
9788 LastIteration.
get(), UB.
get());
9789 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
9814 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
9817 LastIteration.
get(), CombUB.
get());
9818 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
9823 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9827 "Unexpected number of parameters in loop combined directive");
9868 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
9874 bool UseStrictCompare =
9876 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
9877 return LIS.IsStrictCompare;
9883 if (UseStrictCompare) {
9886 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9898 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
9901 NumIterations.
get());
9904 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
9905 NumIterations.
get());
9910 Expr *BoundCombUB = CombUB.
get();
9911 if (UseStrictCompare) {
9915 CurScope, CondLoc, BO_Add, BoundCombUB,
9923 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9924 IV.
get(), BoundCombUB);
9931 if (!Inc.isUsable())
9933 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
9935 if (!Inc.isUsable())
9942 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
9975 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
9987 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
10001 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10004 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
10005 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
10009 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10010 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
10014 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
10025 DistEUBLoc, NewPrevUB.
get());
10030 UB.
get(), NewPrevUB.
get());
10032 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
10033 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
10041 Expr *BoundPrevUB = PrevUB.
get();
10042 if (UseStrictCompare) {
10046 CurScope, CondLoc, BO_Add, BoundPrevUB,
10054 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10055 IV.
get(), BoundPrevUB);
10059 bool HasErrors =
false;
10060 Built.
Counters.resize(NestedLoopCount);
10061 Built.
Inits.resize(NestedLoopCount);
10062 Built.
Updates.resize(NestedLoopCount);
10063 Built.
Finals.resize(NestedLoopCount);
10084 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10085 LoopIterationSpace &IS = IterSpaces[Cnt];
10091 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10092 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
10093 IterSpaces[K].NumIterations);
10098 if (Cnt + 1 < NestedLoopCount)
10103 if (!
Iter.isUsable()) {
10112 if (Cnt + 1 < NestedLoopCount)
10117 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
10120 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10122 SemaRef, VD, IS.CounterVar->
getType(), IS.CounterVar->getExprLoc(),
10126 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10127 if (!
Init.isUsable()) {
10132 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
Iter,
10133 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10134 if (!
Update.isUsable()) {
10142 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10143 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10144 if (!Final.isUsable()) {
10149 if (!
Update.isUsable() || !Final.isUsable()) {
10154 Built.
Counters[Cnt] = IS.CounterVar;
10158 Built.
Finals[Cnt] = Final.get();
10162 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10181 Built.
PreCond = PreCond.get();
10185 Built.
Inc = Inc.get();
10186 Built.
LB = LB.
get();
10187 Built.
UB = UB.
get();
10188 Built.
IL = IL.
get();
10189 Built.
ST = ST.
get();
10191 Built.
NLB = NextLB.
get();
10192 Built.
NUB = NextUB.
get();
10207 return NestedLoopCount;
10211 auto CollapseClauses =
10212 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10213 if (CollapseClauses.begin() != CollapseClauses.end())
10214 return (*CollapseClauses.begin())->getNumForLoops();
10219 auto OrderedClauses =
10220 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10221 if (OrderedClauses.begin() != OrderedClauses.end())
10222 return (*OrderedClauses.begin())->getNumForLoops();
10231 for (
const OMPClause *Clause : Clauses) {
10233 Safelen = cast<OMPSafelenClause>(Clause);
10235 Simdlen = cast<OMPSimdlenClause>(Clause);
10236 if (Safelen && Simdlen)
10240 if (Simdlen && Safelen) {
10254 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
10255 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
10260 if (SimdlenRes > SafelenRes) {
10262 diag::err_omp_wrong_simdlen_safelen_values)
10278 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10285 if (NestedLoopCount == 0)
10295 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10296 return SimdDirective;
10305 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10312 if (NestedLoopCount == 0)
10319 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10321 return ForDirective;
10332 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10336 unsigned NestedLoopCount =
10339 VarsWithImplicitDSA, B);
10340 if (NestedLoopCount == 0)
10350 NestedLoopCount, Clauses, AStmt, B);
10354 Stmt *AStmt, DSAStackTy *Stack) {
10358 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10359 auto BaseStmt = AStmt;
10360 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10362 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10363 auto S =
C->children();
10364 if (S.begin() == S.end())
10368 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
10369 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10371 SemaRef.
Diag(SectionStmt->getBeginLoc(),
10372 diag::err_omp_sections_substmt_not_section)
10373 << getOpenMPDirectiveName(DKind);
10376 cast<OMPSectionDirective>(SectionStmt)
10377 ->setHasCancel(Stack->isCancelRegion());
10380 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10381 << getOpenMPDirectiveName(DKind);
10416 if (
auto *CE = dyn_cast<CallExpr>(
E))
10417 if (CE->getDirectCallee())
10429 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10439 Expr *TargetCall =
nullptr;
10441 auto *
E = dyn_cast<Expr>(S);
10443 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10449 if (
auto *BO = dyn_cast<BinaryOperator>(
E)) {
10450 if (BO->getOpcode() == BO_Assign)
10453 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(
E))
10454 if (COCE->getOperator() == OO_Equal)
10469 Clauses, AStmt, TargetCallLoc);
10474 DSAStackTy *Stack) {
10475 bool ErrorFound =
false;
10477 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
10478 for (
Expr *RefExpr : LPC->varlist()) {
10481 Expr *SimpleRefExpr = RefExpr;
10484 auto &&Info = Stack->isLoopControlVariable(
D);
10486 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10487 << getOpenMPDirectiveName(K);
10516 if (NestedLoopCount == 0)
10520 "omp loop exprs were not built");
10523 NestedLoopCount, Clauses, AStmt, B);
10542 unsigned NestedLoopCount =
10545 VarsWithImplicitDSA, B);
10546 if (NestedLoopCount == 0)
10550 "omp loop exprs were not built");
10552 DSAStack->setParentTeamsRegionLoc(StartLoc);
10555 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10576 unsigned NestedLoopCount =
10579 VarsWithImplicitDSA, B);
10580 if (NestedLoopCount == 0)
10584 "omp loop exprs were not built");
10587 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10609 unsigned NestedLoopCount =
10612 VarsWithImplicitDSA, B);
10613 if (NestedLoopCount == 0)
10617 "omp loop exprs were not built");
10620 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10641 unsigned NestedLoopCount =
10644 VarsWithImplicitDSA, B);
10645 if (NestedLoopCount == 0)
10649 "omp loop exprs were not built");
10652 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10662 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10669 const OMPClause *Copyprivate =
nullptr;
10670 for (
const OMPClause *Clause : Clauses) {
10674 Copyprivate = Clause;
10675 if (Copyprivate && Nowait) {
10677 diag::err_omp_single_copyprivate_with_nowait);
10717 bool ErrorFound =
false;
10720 bool DependentHint =
false;
10722 if (
C->getClauseKind() == OMPC_hint) {
10724 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10727 Expr *
E = cast<OMPHintClause>(
C)->getHint();
10730 DependentHint =
true;
10733 HintLoc =
C->getBeginLoc();
10739 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
10740 if (Pair.first && DirName.
getName() && !DependentHint) {
10741 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10742 Diag(StartLoc, diag::err_omp_critical_with_hint);
10744 Diag(HintLoc, diag::note_omp_critical_hint_here)
10745 << 0 <<
toString(Hint, 10,
false);
10747 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10748 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
10749 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
10754 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10762 EndLoc, Clauses, AStmt);
10763 if (!Pair.first && DirName.
getName() && !DependentHint)
10764 DSAStack->addCriticalWithHint(Dir, Hint);
10779 unsigned NestedLoopCount =
10782 VarsWithImplicitDSA, B);
10783 if (NestedLoopCount == 0)
10790 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10806 unsigned NestedLoopCount =
10809 VarsWithImplicitDSA, B);
10810 if (NestedLoopCount == 0)
10820 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10833 DSAStack->getTaskgroupReductionRef());
10846 DSAStack->getTaskgroupReductionRef());
10867 bool ErrorFound =
false;
10869 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
10873 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10874 << getOpenMPClauseName(
C->getClauseKind())
10896 {OMPC_detach, OMPC_mergeable}))
10902 AStmt,
DSAStack->isCancelRegion());
10918 bool InExContext) {
10920 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
10922 if (AtC && !InExContext && AtC->
getAtKind() == OMPC_AT_execution) {
10928 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
10930 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
10933 if (!AtC || AtC->
getAtKind() == OMPC_AT_compilation) {
10934 if (SeverityC && SeverityC->
getSeverityKind() == OMPC_SEVERITY_warning)
10936 << (ME ? cast<StringLiteral>(ME)->getString() :
"WARNING");
10938 Diag(StartLoc, diag::err_diagnose_if_succeeded)
10939 << (ME ? cast<StringLiteral>(ME)->getString() :
"ERROR");
10940 if (!SeverityC || SeverityC->
getSeverityKind() != OMPC_SEVERITY_warning)
10951 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
10953 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
10955 if (NowaitC && !HasDependC) {
10956 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
10971 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
10977 DSAStack->getTaskgroupReductionRef());
10986 if (
C->getClauseKind() == OMPC_flush)
10987 FC = cast<OMPFlushClause>(
C);
10994 if (
C->getClauseKind() == OMPC_acq_rel ||
10995 C->getClauseKind() == OMPC_acquire ||
10996 C->getClauseKind() == OMPC_release) {
10997 if (MemOrderKind != OMPC_unknown) {
10998 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
10999 << getOpenMPDirectiveName(OMPD_flush) << 1
11001 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11002 << getOpenMPClauseName(MemOrderKind);
11004 MemOrderKind =
C->getClauseKind();
11005 MemOrderLoc =
C->getBeginLoc();
11009 if (FC && OrderClause) {
11012 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
11022 if (Clauses.empty()) {
11023 Diag(StartLoc, diag::err_omp_depobj_expected);
11025 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11026 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11030 if (Clauses.size() > 2) {
11031 Diag(Clauses[2]->getBeginLoc(),
11032 diag::err_omp_depobj_single_clause_expected);
11034 }
else if (Clauses.size() < 1) {
11035 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11045 if (Clauses.size() != 1) {
11046 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11047 diag::err_omp_scan_single_clause_expected);
11052 Scope *ParentS = S->getParent();
11055 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11056 << getOpenMPDirectiveName(OMPD_scan) << 5);
11060 if (
DSAStack->doesParentHasScanDirective()) {
11061 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
11063 diag::note_omp_previous_directive)
11067 DSAStack->setParentHasScanDirective(StartLoc);
11075 const OMPClause *DependFound =
nullptr;
11076 const OMPClause *DependSourceClause =
nullptr;
11077 const OMPClause *DependSinkClause =
nullptr;
11078 const OMPClause *DoacrossFound =
nullptr;
11079 const OMPClause *DoacrossSourceClause =
nullptr;
11080 const OMPClause *DoacrossSinkClause =
nullptr;
11081 bool ErrorFound =
false;
11085 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
11086 auto DC = dyn_cast<OMPDependClause>(
C);
11088 DependFound = DC ?
C :
nullptr;
11089 DoacrossFound = DOC ?
C :
nullptr;
11090 OMPDoacrossKind ODK;
11091 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11092 (DOC && (ODK.isSource(DOC)))) {
11093 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11094 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
11095 << getOpenMPDirectiveName(OMPD_ordered)
11096 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11100 DependSourceClause =
C;
11102 DoacrossSourceClause =
C;
11104 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11105 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11106 << (DC ?
"depend" :
"doacross") << 0;
11109 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11110 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11111 if (DependSourceClause || DoacrossSourceClause) {
11112 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11113 << (DC ?
"depend" :
"doacross") << 1;
11117 DependSinkClause =
C;
11119 DoacrossSinkClause =
C;
11121 }
else if (
C->getClauseKind() == OMPC_threads) {
11122 TC = cast<OMPThreadsClause>(
C);
11123 }
else if (
C->getClauseKind() == OMPC_simd) {
11124 SC = cast<OMPSIMDClause>(
C);
11127 if (!ErrorFound && !SC &&
11132 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11135 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
11138 Diag(
Loc, diag::err_omp_depend_clause_thread_simd)
11139 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11142 }
else if ((DependFound || DoacrossFound) &&
11143 !
DSAStack->getParentOrderedRegionParam().first) {
11146 Diag(
Loc, diag::err_omp_ordered_directive_without_param)
11147 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11149 }
else if (TC || Clauses.empty()) {
11150 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
11152 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11153 << (TC !=
nullptr);
11158 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11166 if (!DependFound && !DoacrossFound) {
11167 if (
DSAStack->doesParentHasOrderedDirective()) {
11168 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
11170 diag::note_omp_previous_directive)
11174 DSAStack->setParentHasOrderedDirective(StartLoc);
11178 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
11190class OpenMPAtomicUpdateChecker {
11192 enum ExprAnalysisErrorCode {
11196 NotABinaryOrUnaryExpression,
11198 NotAnUnaryIncDecExpression,
11204 NotABinaryExpression,
11207 NotABinaryOperator,
11210 NotAnUpdateExpression,
11213 NotAValidExpression,
11231 bool IsXLHSInRHSPart;
11236 bool IsPostfixUpdate;
11239 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
11240 : SemaRef(SemaRef),
X(nullptr),
E(nullptr), UpdateExpr(nullptr),
11241 IsXLHSInRHSPart(
false), Op(BO_PtrMemD), IsPostfixUpdate(
false) {}
11249 bool checkStatement(
Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
11251 Expr *getX()
const {
return X; }
11253 Expr *getExpr()
const {
return E; }
11257 Expr *getUpdateExpr()
const {
return UpdateExpr; }
11260 bool isXLHSInRHSPart()
const {
return IsXLHSInRHSPart; }
11264 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11267 bool checkBinaryOperation(
BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
11268 unsigned NoteId = 0);
11271bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11272 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
11273 ExprAnalysisErrorCode ErrorFound = NoError;
11279 if (AtomicBinOp->
getOpcode() == BO_Assign) {
11281 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11283 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11284 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11285 AtomicInnerBinOp->isBitwiseOp()) {
11286 Op = AtomicInnerBinOp->getOpcode();
11287 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11288 Expr *LHS = AtomicInnerBinOp->getLHS();
11289 Expr *RHS = AtomicInnerBinOp->getRHS();
11290 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11297 if (XId == LHSId) {
11299 IsXLHSInRHSPart =
true;
11300 }
else if (XId == RHSId) {
11302 IsXLHSInRHSPart =
false;
11304 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11305 ErrorRange = AtomicInnerBinOp->getSourceRange();
11306 NoteLoc =
X->getExprLoc();
11307 NoteRange =
X->getSourceRange();
11308 ErrorFound = NotAnUpdateExpression;
11311 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11312 ErrorRange = AtomicInnerBinOp->getSourceRange();
11313 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11315 ErrorFound = NotABinaryOperator;
11320 ErrorFound = NotABinaryExpression;
11327 ErrorFound = NotAnAssignmentOp;
11329 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11330 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11331 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11335 E =
X = UpdateExpr =
nullptr;
11336 return ErrorFound != NoError;
11339bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
11341 ExprAnalysisErrorCode ErrorFound = NoError;
11352 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
11353 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11354 if (AtomicBody->getType()->isScalarType() ||
11355 AtomicBody->isInstantiationDependent()) {
11356 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11357 AtomicBody->IgnoreParenImpCasts())) {
11360 AtomicCompAssignOp->getOpcode());
11361 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11362 E = AtomicCompAssignOp->getRHS();
11363 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11364 IsXLHSInRHSPart =
true;
11365 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11366 AtomicBody->IgnoreParenImpCasts())) {
11368 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11370 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11371 AtomicBody->IgnoreParenImpCasts())) {
11373 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11374 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11375 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11376 OpLoc = AtomicUnaryOp->getOperatorLoc();
11377 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11379 IsXLHSInRHSPart =
true;
11381 ErrorFound = NotAnUnaryIncDecExpression;
11382 ErrorLoc = AtomicUnaryOp->getExprLoc();
11383 ErrorRange = AtomicUnaryOp->getSourceRange();
11384 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11387 }
else if (!AtomicBody->isInstantiationDependent()) {
11388 ErrorFound = NotABinaryOrUnaryExpression;
11389 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11390 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11391 }
else if (AtomicBody->containsErrors()) {
11392 ErrorFound = NotAValidExpression;
11393 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11394 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11397 ErrorFound = NotAScalarType;
11398 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11399 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11402 ErrorFound = NotAnExpression;
11403 NoteLoc = ErrorLoc = S->getBeginLoc();
11404 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
11406 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11407 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
11408 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11412 E =
X = UpdateExpr =
nullptr;
11413 if (ErrorFound == NoError &&
E &&
X) {
11423 IsXLHSInRHSPart ? OVEExpr : OVEX);
11430 UpdateExpr =
Update.get();
11432 return ErrorFound != NoError;
11436llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
11437 llvm::FoldingSetNodeID
Id;
11438 S->IgnoreParenImpCasts()->Profile(
Id, Context,
true);
11443bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
11445 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11448class OpenMPAtomicCompareChecker {
11495 struct ErrorInfoTy {
11503 OpenMPAtomicCompareChecker(
Sema &S) : ContextRef(S.getASTContext()) {}
11506 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11508 Expr *getX()
const {
return X; }
11509 Expr *getE()
const {
return E; }
11510 Expr *getD()
const {
return D; }
11511 Expr *getCond()
const {
return C; }
11512 bool isXBinopExpr()
const {
return IsXBinopExpr; }
11531 bool IsXBinopExpr =
true;
11534 bool checkCondUpdateStmt(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11537 bool checkCondExprStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11540 bool checkType(ErrorInfoTy &ErrorInfo)
const;
11542 static bool CheckValue(
const Expr *
E, ErrorInfoTy &ErrorInfo,
11543 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
11547 if (ShouldBeLValue && !
E->
isLValue()) {
11548 ErrorInfo.Error = ErrorTy::XNotLValue;
11549 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11556 ErrorInfo.Error = ErrorTy::NotScalar;
11557 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11562 ErrorInfo.Error = ErrorTy::NotInteger;
11563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc =
E->
getExprLoc();
11572bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
11573 ErrorInfoTy &ErrorInfo) {
11574 auto *Then = S->getThen();
11575 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11576 if (CS->body_empty()) {
11577 ErrorInfo.Error = ErrorTy::NoStmt;
11578 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11579 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11582 if (CS->size() > 1) {
11583 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11584 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11585 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11588 Then = CS->body_front();
11591 auto *BO = dyn_cast<BinaryOperator>(Then);
11593 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11594 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11595 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11598 if (BO->getOpcode() != BO_Assign) {
11599 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11600 ErrorInfo.ErrorLoc = BO->getExprLoc();
11601 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11602 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11608 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11610 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11611 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11612 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11616 switch (Cond->getOpcode()) {
11620 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11621 E = Cond->getRHS();
11622 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11623 E = Cond->getLHS();
11625 ErrorInfo.Error = ErrorTy::InvalidComparison;
11626 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11627 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11635 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS()) &&
11636 checkIfTwoExprsAreSame(ContextRef,
E, Cond->getRHS())) {
11638 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, Cond->getLHS()) &&
11639 checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11641 IsXBinopExpr =
false;
11643 ErrorInfo.Error = ErrorTy::InvalidComparison;
11644 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11645 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11651 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11652 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11653 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11657 if (S->getElse()) {
11658 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11659 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11660 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11667bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
11668 ErrorInfoTy &ErrorInfo) {
11669 auto *BO = dyn_cast<BinaryOperator>(S);
11671 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11672 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11673 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11676 if (BO->getOpcode() != BO_Assign) {
11677 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11678 ErrorInfo.ErrorLoc = BO->getExprLoc();
11679 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11680 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11686 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11688 ErrorInfo.Error = ErrorTy::NotCondOp;
11689 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11690 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11694 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
11695 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11696 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11697 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11698 CO->getFalseExpr()->getSourceRange();
11702 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11704 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11705 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11706 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11707 CO->getCond()->getSourceRange();
11711 switch (Cond->getOpcode()) {
11714 D = CO->getTrueExpr();
11715 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11716 E = Cond->getRHS();
11717 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11718 E = Cond->getLHS();
11720 ErrorInfo.Error = ErrorTy::InvalidComparison;
11721 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11722 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11729 E = CO->getTrueExpr();
11730 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS()) &&
11731 checkIfTwoExprsAreSame(ContextRef,
E, Cond->getRHS())) {
11733 }
else if (checkIfTwoExprsAreSame(ContextRef,
E, Cond->getLHS()) &&
11734 checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11736 IsXBinopExpr =
false;
11738 ErrorInfo.Error = ErrorTy::InvalidComparison;
11739 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11740 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11746 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11747 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11748 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11755bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
11757 assert(
X &&
E &&
"X and E cannot be nullptr");
11759 if (!CheckValue(
X, ErrorInfo,
true))
11762 if (!CheckValue(
E, ErrorInfo,
false))
11765 if (
D && !CheckValue(
D, ErrorInfo,
false))
11771bool OpenMPAtomicCompareChecker::checkStmt(
11772 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11773 auto *CS = dyn_cast<CompoundStmt>(S);
11775 if (CS->body_empty()) {
11776 ErrorInfo.Error = ErrorTy::NoStmt;
11777 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11778 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11782 if (CS->size() != 1) {
11783 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11784 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11785 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11788 S = CS->body_front();
11793 if (
auto *IS = dyn_cast<IfStmt>(S)) {
11799 Res = checkCondUpdateStmt(IS, ErrorInfo);
11805 Res = checkCondExprStmt(S, ErrorInfo);
11811 return checkType(ErrorInfo);
11814class OpenMPAtomicCompareCaptureChecker final
11815 :
public OpenMPAtomicCompareChecker {
11817 OpenMPAtomicCompareCaptureChecker(
Sema &S) : OpenMPAtomicCompareChecker(S) {}
11819 Expr *getV()
const {
return V; }
11820 Expr *getR()
const {
return R; }
11821 bool isFailOnly()
const {
return IsFailOnly; }
11822 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
11825 bool checkStmt(
Stmt *S, ErrorInfoTy &ErrorInfo);
11828 bool checkType(ErrorInfoTy &ErrorInfo);
11840 bool checkForm3(
IfStmt *S, ErrorInfoTy &ErrorInfo);
11844 bool checkForm45(
Stmt *S, ErrorInfoTy &ErrorInfo);
11851 bool IsFailOnly =
false;
11853 bool IsPostfixUpdate =
false;
11856bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11857 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11860 if (
V && !CheckValue(
V, ErrorInfo,
true))
11863 if (R && !CheckValue(R, ErrorInfo,
true,
true))
11869bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
11870 ErrorInfoTy &ErrorInfo) {
11873 auto *Then = S->getThen();
11874 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
11875 if (CS->body_empty()) {
11876 ErrorInfo.Error = ErrorTy::NoStmt;
11877 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11878 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11881 if (CS->size() > 1) {
11882 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11883 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11884 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11887 Then = CS->body_front();
11890 auto *BO = dyn_cast<BinaryOperator>(Then);
11892 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11893 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11894 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11897 if (BO->getOpcode() != BO_Assign) {
11898 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11899 ErrorInfo.ErrorLoc = BO->getExprLoc();
11900 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11901 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11908 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11910 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11911 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11912 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11915 if (Cond->getOpcode() != BO_EQ) {
11916 ErrorInfo.Error = ErrorTy::NotEQ;
11917 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11918 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11922 if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getLHS())) {
11923 E = Cond->getRHS();
11924 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, Cond->getRHS())) {
11925 E = Cond->getLHS();
11927 ErrorInfo.Error = ErrorTy::InvalidComparison;
11928 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->
getExprLoc();
11929 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
11935 if (!S->getElse()) {
11936 ErrorInfo.Error = ErrorTy::NoElse;
11937 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11938 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11942 auto *Else = S->getElse();
11943 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
11944 if (CS->body_empty()) {
11945 ErrorInfo.Error = ErrorTy::NoStmt;
11946 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11947 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
11950 if (CS->size() > 1) {
11951 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11952 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
11953 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11956 Else = CS->body_front();
11959 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
11961 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11962 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
11963 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
11966 if (ElseBO->getOpcode() != BO_Assign) {
11967 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11968 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
11969 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
11970 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
11974 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
11975 ErrorInfo.Error = ErrorTy::InvalidAssignment;
11976 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
11977 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11978 ElseBO->getRHS()->getSourceRange();
11982 V = ElseBO->getLHS();
11984 return checkType(ErrorInfo);
11987bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
11988 ErrorInfoTy &ErrorInfo) {
11991 auto *CS = cast<CompoundStmt>(S);
11992 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
11993 auto *S1 = cast<BinaryOperator>(CS->body_front());
11994 auto *S2 = cast<IfStmt>(CS->body_back());
11995 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
11997 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
11998 ErrorInfo.Error = ErrorTy::InvalidCondition;
11999 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12000 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12006 auto *Then = S2->getThen();
12007 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12008 if (ThenCS->body_empty()) {
12009 ErrorInfo.Error = ErrorTy::NoStmt;
12010 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12011 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12014 if (ThenCS->size() > 1) {
12015 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12016 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12017 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12020 Then = ThenCS->body_front();
12023 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12025 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12026 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12027 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12030 if (ThenBO->getOpcode() != BO_Assign) {
12031 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12032 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12033 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12034 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12038 X = ThenBO->getLHS();
12039 D = ThenBO->getRHS();
12041 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12042 if (BO->getOpcode() != BO_EQ) {
12043 ErrorInfo.Error = ErrorTy::NotEQ;
12044 ErrorInfo.ErrorLoc = BO->getExprLoc();
12045 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12046 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12052 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
12054 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
12057 ErrorInfo.Error = ErrorTy::InvalidComparison;
12058 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->
getExprLoc();
12059 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12063 if (S2->getElse()) {
12066 auto *Else = S2->getElse();
12067 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12068 if (ElseCS->body_empty()) {
12069 ErrorInfo.Error = ErrorTy::NoStmt;
12070 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12071 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12074 if (ElseCS->size() > 1) {
12075 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12080 Else = ElseCS->body_front();
12083 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12085 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12090 if (ElseBO->getOpcode() != BO_Assign) {
12091 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12092 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12093 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12094 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12097 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
12098 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12099 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12100 ErrorInfo.NoteLoc =
X->getExprLoc();
12101 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12102 ErrorInfo.NoteRange =
X->getSourceRange();
12106 V = ElseBO->getLHS();
12109 return checkType(ErrorInfo);
12112bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
12113 ErrorInfoTy &ErrorInfo) {
12115 if (
auto *IS = dyn_cast<IfStmt>(S))
12116 return checkForm3(IS, ErrorInfo);
12118 auto *CS = dyn_cast<CompoundStmt>(S);
12120 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12121 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12122 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12125 if (CS->body_empty()) {
12126 ErrorInfo.Error = ErrorTy::NoStmt;
12127 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12128 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12133 if (CS->size() == 1) {
12134 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12136 ErrorInfo.Error = ErrorTy::NotIfStmt;
12137 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
12138 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12143 return checkForm3(IS, ErrorInfo);
12144 }
else if (CS->size() == 2) {
12145 auto *S1 = CS->body_front();
12146 auto *S2 = CS->body_back();
12148 Stmt *UpdateStmt =
nullptr;
12149 Stmt *CondUpdateStmt =
nullptr;
12150 Stmt *CondExprStmt =
nullptr;
12152 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
12158 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12159 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12161 if (isa<IfStmt>(S2))
12162 return checkForm45(CS, ErrorInfo);
12167 IsPostfixUpdate =
true;
12169 if (isa<IfStmt>(S2)) {
12171 CondUpdateStmt = S2;
12180 CondUpdateStmt = S1;
12183 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
12184 auto *IS = dyn_cast<IfStmt>(CUS);
12186 ErrorInfo.Error = ErrorTy::NotIfStmt;
12187 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12188 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12192 return checkCondUpdateStmt(IS, ErrorInfo);
12196 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
12197 auto *BO = dyn_cast<BinaryOperator>(US);
12199 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12200 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12201 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12204 if (BO->getOpcode() != BO_Assign) {
12205 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12206 ErrorInfo.ErrorLoc = BO->getExprLoc();
12207 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12208 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12211 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12212 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12213 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12215 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12220 this->
V = BO->getLHS();
12225 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12227 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12229 if (!CheckUpdateStmt(UpdateStmt))
12232 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12233 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
12234 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
12238 return checkType(ErrorInfo);
12248 DSAStack->addAtomicDirectiveLoc(StartLoc);
12261 bool MutexClauseEncountered =
false;
12262 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12264 switch (
C->getClauseKind()) {
12268 MutexClauseEncountered =
true;
12271 case OMPC_compare: {
12272 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12273 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12275 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12276 << getOpenMPClauseName(AtomicKind);
12278 AtomicKind =
C->getClauseKind();
12279 AtomicKindLoc =
C->getBeginLoc();
12280 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
12281 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12283 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12284 << getOpenMPClauseName(AtomicKind);
12291 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12292 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12293 << getOpenMPClauseName(
C->getClauseKind())
12303 case OMPC_relaxed: {
12304 if (MemOrderKind != OMPC_unknown) {
12305 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12306 << getOpenMPDirectiveName(OMPD_atomic) << 0
12308 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12309 << getOpenMPClauseName(MemOrderKind);
12311 MemOrderKind =
C->getClauseKind();
12312 MemOrderLoc =
C->getBeginLoc();
12320 llvm_unreachable(
"unknown clause is encountered");
12323 bool IsCompareCapture =
false;
12324 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12325 EncounteredAtomicKinds.contains(OMPC_capture)) {
12326 IsCompareCapture =
true;
12327 AtomicKind = OMPC_compare;
12336 if ((AtomicKind == OMPC_read &&
12337 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12338 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12339 AtomicKind == OMPC_unknown) &&
12340 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12342 if (AtomicKind == OMPC_unknown)
12344 Diag(
Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12345 << getOpenMPClauseName(AtomicKind)
12346 << (AtomicKind == OMPC_unknown ? 1 : 0)
12347 << getOpenMPClauseName(MemOrderKind);
12348 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12349 << getOpenMPClauseName(MemOrderKind);
12352 Stmt *Body = AStmt;
12353 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12354 Body = EWC->getSubExpr();
12359 Expr *UE =
nullptr;
12361 Expr *CE =
nullptr;
12363 bool IsXLHSInRHSPart =
false;
12364 bool IsPostfixUpdate =
false;
12365 bool IsFailOnly =
false;
12388 if (AtomicKind == OMPC_read) {
12395 } ErrorFound = NoError;
12400 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12401 const auto *AtomicBinOp =
12402 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12403 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12406 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12407 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
12408 if (!
X->isLValue() || !
V->isLValue()) {
12409 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
12410 ErrorFound = NotAnLValue;
12416 }
else if (!
X->isInstantiationDependent() ||
12417 !
V->isInstantiationDependent()) {
12418 const Expr *NotScalarExpr =
12419 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12422 ErrorFound = NotAScalarType;
12428 }
else if (!AtomicBody->isInstantiationDependent()) {
12429 ErrorFound = NotAnAssignmentOp;
12430 ErrorLoc = AtomicBody->getExprLoc();
12431 ErrorRange = AtomicBody->getSourceRange();
12433 : AtomicBody->getExprLoc();
12435 : AtomicBody->getSourceRange();
12438 ErrorFound = NotAnExpression;
12440 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12442 if (ErrorFound != NoError) {
12443 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12445 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12446 << ErrorFound << NoteRange;
12451 }
else if (AtomicKind == OMPC_write) {
12458 } ErrorFound = NoError;
12463 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12464 const auto *AtomicBinOp =
12465 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12466 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12469 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
12471 if (!
X->isLValue()) {
12472 ErrorFound = NotAnLValue;
12475 NoteLoc =
X->getExprLoc();
12476 NoteRange =
X->getSourceRange();
12478 }
else if (!
X->isInstantiationDependent() ||
12480 const Expr *NotScalarExpr =
12481 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
12484 ErrorFound = NotAScalarType;
12490 }
else if (!AtomicBody->isInstantiationDependent()) {
12491 ErrorFound = NotAnAssignmentOp;
12492 ErrorLoc = AtomicBody->getExprLoc();
12493 ErrorRange = AtomicBody->getSourceRange();
12495 : AtomicBody->getExprLoc();
12497 : AtomicBody->getSourceRange();
12500 ErrorFound = NotAnExpression;
12502 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12504 if (ErrorFound != NoError) {
12505 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12507 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12508 << ErrorFound << NoteRange;
12513 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12522 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12523 if (Checker.checkStatement(
12525 (AtomicKind == OMPC_update)
12526 ? diag::err_omp_atomic_update_not_expression_statement
12527 : diag::err_omp_atomic_not_expression_statement,
12528 diag::note_omp_atomic_update))
12531 E = Checker.getExpr();
12532 X = Checker.getX();
12533 UE = Checker.getUpdateExpr();
12534 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12536 }
else if (AtomicKind == OMPC_capture) {
12539 NotACompoundStatement,
12540 NotTwoSubstatements,
12541 NotASpecificExpression,
12543 } ErrorFound = NoError;
12546 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12555 const auto *AtomicBinOp =
12556 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12557 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
12560 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12561 if (Checker.checkStatement(
12562 Body, diag::err_omp_atomic_capture_not_expression_statement,
12563 diag::note_omp_atomic_update))
12565 E = Checker.getExpr();
12566 X = Checker.getX();
12567 UE = Checker.getUpdateExpr();
12568 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12569 IsPostfixUpdate = Checker.isPostfixUpdate();
12570 }
else if (!AtomicBody->isInstantiationDependent()) {
12571 ErrorLoc = AtomicBody->getExprLoc();
12572 ErrorRange = AtomicBody->getSourceRange();
12574 : AtomicBody->getExprLoc();
12576 : AtomicBody->getSourceRange();
12577 ErrorFound = NotAnAssignmentOp;
12579 if (ErrorFound != NoError) {
12580 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12582 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12586 UE =
V =
E =
X =
nullptr;
12604 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
12606 if (CS->size() == 2) {
12608 Stmt *Second = CS->body_back();
12609 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
12610 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12611 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12612 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12614 OpenMPAtomicUpdateChecker Checker(
SemaRef);
12615 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12617 if (IsUpdateExprFound) {
12618 BinOp = dyn_cast<BinaryOperator>(
First);
12619 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
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 =
true;
12644 if (!IsUpdateExprFound) {
12645 IsUpdateExprFound = !Checker.checkStatement(
First);
12647 if (IsUpdateExprFound) {
12648 BinOp = dyn_cast<BinaryOperator>(Second);
12649 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
12651 if (IsUpdateExprFound &&
12662 llvm::FoldingSetNodeID XId, PossibleXId;
12663 Checker.getX()->
Profile(XId, Context,
true);
12664 PossibleX->
Profile(PossibleXId, Context,
true);
12665 IsUpdateExprFound = XId == PossibleXId;
12666 if (IsUpdateExprFound) {
12668 X = Checker.getX();
12669 E = Checker.getExpr();
12670 UE = Checker.getUpdateExpr();
12671 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12672 IsPostfixUpdate =
false;
12676 if (!IsUpdateExprFound) {
12678 auto *FirstExpr = dyn_cast<Expr>(
First);
12679 auto *SecondExpr = dyn_cast<Expr>(Second);
12680 if (!FirstExpr || !SecondExpr ||
12681 !(FirstExpr->isInstantiationDependent() ||
12682 SecondExpr->isInstantiationDependent())) {
12683 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
12684 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12685 ErrorFound = NotAnAssignmentOp;
12686 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12687 :
First->getBeginLoc();
12688 NoteRange = ErrorRange = FirstBinOp
12689 ? FirstBinOp->getSourceRange()
12692 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12693 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12694 ErrorFound = NotAnAssignmentOp;
12695 NoteLoc = ErrorLoc = SecondBinOp
12696 ? SecondBinOp->getOperatorLoc()
12698 NoteRange = ErrorRange =
12699 SecondBinOp ? SecondBinOp->getSourceRange()
12702 Expr *PossibleXRHSInFirst =
12704 Expr *PossibleXLHSInSecond =
12706 llvm::FoldingSetNodeID X1Id, X2Id;
12707 PossibleXRHSInFirst->
Profile(X1Id, Context,
12709 PossibleXLHSInSecond->
Profile(X2Id, Context,
12711 IsUpdateExprFound = X1Id == X2Id;
12712 if (IsUpdateExprFound) {
12713 V = FirstBinOp->getLHS();
12714 X = SecondBinOp->getLHS();
12715 E = SecondBinOp->getRHS();
12717 IsXLHSInRHSPart =
false;
12718 IsPostfixUpdate =
true;
12720 ErrorFound = NotASpecificExpression;
12721 ErrorLoc = FirstBinOp->getExprLoc();
12722 ErrorRange = FirstBinOp->getSourceRange();
12723 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12724 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12732 NoteRange = ErrorRange =
12734 ErrorFound = NotTwoSubstatements;
12738 NoteRange = ErrorRange =
12740 ErrorFound = NotACompoundStatement;
12743 if (ErrorFound != NoError) {
12744 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12746 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12750 UE =
V =
E =
X =
nullptr;
12751 }
else if (AtomicKind == OMPC_compare) {
12752 if (IsCompareCapture) {
12753 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12754 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
12755 if (!Checker.checkStmt(Body, ErrorInfo)) {
12756 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12757 << ErrorInfo.ErrorRange;
12758 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12759 << ErrorInfo.Error << ErrorInfo.NoteRange;
12762 X = Checker.getX();
12763 E = Checker.getE();
12764 D = Checker.getD();
12765 CE = Checker.getCond();
12766 V = Checker.getV();
12767 R = Checker.getR();
12769 IsXLHSInRHSPart = Checker.isXBinopExpr();
12770 IsFailOnly = Checker.isFailOnly();
12771 IsPostfixUpdate = Checker.isPostfixUpdate();
12773 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12774 OpenMPAtomicCompareChecker Checker(
SemaRef);
12775 if (!Checker.checkStmt(Body, ErrorInfo)) {
12776 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12777 << ErrorInfo.ErrorRange;
12778 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12779 << ErrorInfo.Error << ErrorInfo.NoteRange;
12782 X = Checker.getX();
12783 E = Checker.getE();
12784 D = Checker.getD();
12785 CE = Checker.getCond();
12791 auto *It = find_if(Clauses, [](
OMPClause *
C) {
12792 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12794 if (It != Clauses.end()) {
12795 auto *Cond = dyn_cast<BinaryOperator>(CE);
12796 if (Cond->getOpcode() != BO_EQ) {
12797 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12799 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12800 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
12802 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12803 << ErrorInfo.ErrorRange;
12808 IsXLHSInRHSPart = Checker.isXBinopExpr();
12815 Context, StartLoc, EndLoc, Clauses, AStmt,
12816 {
X,
V, R,
E, UE,
D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12832 if (
DSAStack->hasInnerTeamsRegion()) {
12834 bool OMPTeamsFound =
true;
12835 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
12836 auto I = CS->body_begin();
12837 while (I != CS->body_end()) {
12838 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12840 if (!IsTeams || I != CS->body_begin()) {
12841 OMPTeamsFound =
false;
12842 if (IsTeams && I != CS->body_begin()) {
12851 assert(I != CS->body_end() &&
"Not found statement");
12854 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12857 if (!OMPTeamsFound) {
12858 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12860 diag::note_omp_nested_teams_construct_here);
12861 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12862 << isa<OMPExecutableDirective>(S);
12896 unsigned NestedLoopCount =
12899 VarsWithImplicitDSA, B);
12900 if (NestedLoopCount == 0)
12907 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12914 return llvm::any_of(
12915 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
12918template <
typename... Params>
12920 const Params... ClauseTypes) {
12927 if (
auto *TC = dyn_cast<OMPToClause>(
C))
12928 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
12929 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12930 (VD->isExternallyVisible() &&
12931 VD->getVisibility() != HiddenVisibility);
12933 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
12934 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
12935 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12936 (VD->isExternallyVisible() &&
12937 VD->getVisibility() != HiddenVisibility);
12951 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
12956 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
12958 !
hasClauses(Clauses, OMPC_use_device_addr))) {
12961 Expected =
"'map' or 'use_device_ptr'";
12963 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
12964 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12965 <<
Expected << getOpenMPDirectiveName(OMPD_target_data);
12986 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12987 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13006 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13007 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13023 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
13024 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13029 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13039template <
typename ClauseType>
13042 unsigned MaxNum,
unsigned Diag) {
13043 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13044 if (ClauseItr == Clauses.end())
13046 const auto *
C = cast<ClauseType>(*ClauseItr);
13047 auto VarList =
C->getVarRefs();
13048 if (VarList.size() > MaxNum) {
13049 SemaRef.
Diag(VarList[MaxNum]->getBeginLoc(),
Diag)
13050 << getOpenMPClauseName(
C->getClauseKind());
13063 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13064 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13065 !checkNumExprsInClause<OMPThreadLimitClause>(
13066 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13071 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13075 DSAStack->setParentTeamsRegionLoc(StartLoc);
13084 if (
DSAStack->isParentNowaitRegion()) {
13085 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13088 if (
DSAStack->isParentOrderedRegion()) {
13089 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13093 EndLoc, CancelRegion);
13099 if (
DSAStack->isParentNowaitRegion()) {
13100 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13103 if (
DSAStack->isParentOrderedRegion()) {
13104 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13107 DSAStack->setParentCancelRegion(
true);
13114 const OMPClause *ReductionClause =
nullptr;
13115 const OMPClause *NogroupClause =
nullptr;
13117 if (
C->getClauseKind() == OMPC_reduction) {
13118 ReductionClause =
C;
13123 if (
C->getClauseKind() == OMPC_nogroup) {
13125 if (ReductionClause)
13130 if (ReductionClause && NogroupClause) {
13131 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13145 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13149 unsigned NestedLoopCount =
13152 *
DSAStack, VarsWithImplicitDSA, B);
13153 if (NestedLoopCount == 0)
13157 "omp for loop exprs were not built");
13163 {OMPC_grainsize, OMPC_num_tasks}))
13173 NestedLoopCount, Clauses, AStmt, B,
13186 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13190 unsigned NestedLoopCount =
13193 VarsWithImplicitDSA, B);
13194 if (NestedLoopCount == 0)
13204 {OMPC_grainsize, OMPC_num_tasks}))
13215 NestedLoopCount, Clauses, AStmt, B);
13224 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13228 unsigned NestedLoopCount =
13231 *
DSAStack, VarsWithImplicitDSA, B);
13232 if (NestedLoopCount == 0)
13236 "omp for loop exprs were not built");
13242 {OMPC_grainsize, OMPC_num_tasks}))
13252 NestedLoopCount, Clauses, AStmt, B,
13262 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13266 unsigned NestedLoopCount =
13269 *
DSAStack, VarsWithImplicitDSA, B);
13270 if (NestedLoopCount == 0)
13274 "omp for loop exprs were not built");
13280 {OMPC_grainsize, OMPC_num_tasks}))
13290 NestedLoopCount, Clauses, AStmt, B,
13303 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13307 unsigned NestedLoopCount =
13310 VarsWithImplicitDSA, B);
13311 if (NestedLoopCount == 0)
13321 {OMPC_grainsize, OMPC_num_tasks}))
13332 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13344 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13348 unsigned NestedLoopCount =
13351 VarsWithImplicitDSA, B);
13352 if (NestedLoopCount == 0)
13362 {OMPC_grainsize, OMPC_num_tasks}))
13373 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13391 VarsWithImplicitDSA, B);
13392 if (NestedLoopCount == 0)
13396 "omp for loop exprs were not built");
13402 {OMPC_grainsize, OMPC_num_tasks}))
13411 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13430 VarsWithImplicitDSA, B);
13431 if (NestedLoopCount == 0)
13435 "omp for loop exprs were not built");
13441 {OMPC_grainsize, OMPC_num_tasks}))
13450 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13461 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13469 VarsWithImplicitDSA, B);
13470 if (NestedLoopCount == 0)
13480 {OMPC_grainsize, OMPC_num_tasks}))
13491 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13501 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13509 VarsWithImplicitDSA, B);
13510 if (NestedLoopCount == 0)
13520 {OMPC_grainsize, OMPC_num_tasks}))
13531 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13540 assert(isa<CapturedStmt>(AStmt) &&
"Captured statement expected");
13544 unsigned NestedLoopCount =
13548 if (NestedLoopCount == 0)
13552 "omp for loop exprs were not built");
13556 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13557 return DistributeDirective;
13575 VarsWithImplicitDSA, B);
13576 if (NestedLoopCount == 0)
13580 "omp for loop exprs were not built");
13583 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13594 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13602 VarsWithImplicitDSA, B);
13603 if (NestedLoopCount == 0)
13613 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13628 unsigned NestedLoopCount =
13632 if (NestedLoopCount == 0)
13642 NestedLoopCount, Clauses, AStmt, B);
13660 VarsWithImplicitDSA, B);
13661 if (NestedLoopCount == 0)
13671 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13685 unsigned NestedLoopCount =
13688 VarsWithImplicitDSA, B);
13689 if (NestedLoopCount == 0)
13699 NestedLoopCount, Clauses, AStmt, B);
13714 unsigned NestedLoopCount =
13718 if (NestedLoopCount == 0)
13722 "omp teams distribute loop exprs were not built");
13724 DSAStack->setParentTeamsRegionLoc(StartLoc);
13727 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13745 VarsWithImplicitDSA, B);
13746 if (NestedLoopCount == 0)
13755 DSAStack->setParentTeamsRegionLoc(StartLoc);
13758 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13768 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13776 VarsWithImplicitDSA, B);
13777 if (NestedLoopCount == 0)
13786 DSAStack->setParentTeamsRegionLoc(StartLoc);
13789 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13799 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13807 VarsWithImplicitDSA, B);
13809 if (NestedLoopCount == 0)
13813 "omp for loop exprs were not built");
13815 DSAStack->setParentTeamsRegionLoc(StartLoc);
13818 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13831 bool HasThreadLimitAndNumTeamsClause =
hasClauses(Clauses, OMPC_num_teams) &&
13833 bool HasBareClause = llvm::any_of(Clauses, [&](
const OMPClause *
C) {
13835 return C->getClauseKind() == OMPC_ompx_bare;
13838 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13843 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
13844 unsigned DiagNo = HasBareClause
13845 ? diag::err_ompx_more_than_three_expr_not_allowed
13846 : diag::err_omp_multi_expr_not_allowed;
13847 if (!checkNumExprsInClause<OMPNumTeamsClause>(*
this, Clauses,
13848 ClauseMaxNumExprs, DiagNo) ||
13849 !checkNumExprsInClause<OMPThreadLimitClause>(*
this, Clauses,
13850 ClauseMaxNumExprs, DiagNo))
13863 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13864 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13865 !checkNumExprsInClause<OMPThreadLimitClause>(
13866 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13878 VarsWithImplicitDSA, B);
13879 if (NestedLoopCount == 0)
13883 "omp target teams distribute loop exprs were not built");
13886 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13895 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13896 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13897 !checkNumExprsInClause<OMPThreadLimitClause>(
13898 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13902 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
13910 VarsWithImplicitDSA, B);
13911 if (NestedLoopCount == 0)
13918 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13928 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13929 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13930 !checkNumExprsInClause<OMPThreadLimitClause>(
13931 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13935 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
13940 unsigned NestedLoopCount =
13945 if (NestedLoopCount == 0)
13955 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13964 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13965 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed) ||
13966 !checkNumExprsInClause<OMPThreadLimitClause>(
13967 *
this, Clauses, 1, diag::err_omp_multi_expr_not_allowed))
13971 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
13979 VarsWithImplicitDSA, B);
13980 if (NestedLoopCount == 0)
13990 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13993bool SemaOpenMP::checkTransformableLoopNest(
13997 OriginalInits.emplace_back();
14000 [
this, &LoopHelpers, &Body, &OriginalInits, Kind](
unsigned Cnt,
14002 VarsWithInheritedDSAType TmpDSA;
14003 unsigned SingleNumLoops =
14004 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14005 TmpDSA, LoopHelpers[Cnt]);
14006 if (SingleNumLoops == 0)
14008 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
14009 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14010 OriginalInits.back().push_back(For->getInit());
14011 Body = For->getBody();
14013 assert(isa<CXXForRangeStmt>(CurStmt) &&
14014 "Expected canonical for or range-based for loops.");
14015 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14016 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14017 Body = CXXFor->getBody();
14019 OriginalInits.emplace_back();
14023 Stmt *DependentPreInits;
14024 if (
auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14025 DependentPreInits = Dir->getPreInits();
14026 else if (
auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14027 DependentPreInits = Dir->getPreInits();
14028 else if (
auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14029 DependentPreInits = Dir->getPreInits();
14030 else if (
auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14031 DependentPreInits = Dir->getPreInits();
14033 llvm_unreachable(
"Unhandled loop transformation");
14037 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
14038 OriginalInits.pop_back();
14050 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14051 Stmt *RangeInit = CXXRangeFor->getInit();
14053 PreInits.push_back(RangeInit);
14055 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14060 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14066 llvm::append_range(PreInits, OriginalInit);
14069 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.
PreInits)) {
14070 PreInits.push_back(
new (Context)
DeclStmt(
14071 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14076 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14077 if (isa<OMPCapturedExprDecl>(CounterDecl))
14078 PreInits.push_back(
new (Context)
DeclStmt(
14086 size_t NumLoops = LoopStmts.size();
14088 AStmt,
false, NumLoops,
14089 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
14090 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
14091 LoopStmts[Cnt] = CurStmt;
14094 assert(!is_contained(LoopStmts,
nullptr) &&
14095 "Expecting a loop statement for each affected loop");
14105 const auto *SizesClause =
14106 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14107 if (!SizesClause ||
14108 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *
E) { return !E; }))
14110 unsigned NumLoops = SizesClause->getNumSizes();
14118 Stmt *Body =
nullptr;
14120 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14127 NumLoops, AStmt,
nullptr,
nullptr);
14129 assert(LoopHelpers.size() == NumLoops &&
14130 "Expecting loop iteration space dimensionality to match number of "
14132 assert(OriginalInits.size() == NumLoops &&
14133 "Expecting loop iteration space dimensionality to match number of "
14141 CaptureVars CopyTransformer(
SemaRef);
14146 FloorIndVars.resize(NumLoops);
14147 TileIndVars.resize(NumLoops);
14148 for (
unsigned I = 0; I < NumLoops; ++I) {
14151 assert(LoopHelper.
Counters.size() == 1 &&
14152 "Expect single-dimensional loop iteration space");
14153 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14154 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14160 std::string FloorCntName =
14161 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14164 FloorIndVars[I] = FloorCntDecl;
14169 std::string TileCntName =
14170 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
14175 auto *TileCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
14176 TileCntDecl->setDeclName(
14178 TileIndVars[I] = TileCntDecl;
14186 Stmt *Inner = Body;
14188 auto MakeDimTileSize = [&
SemaRef = this->
SemaRef, &CopyTransformer, &Context,
14189 SizesClause, CurScope](
int I) ->
Expr * {
14190 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14191 if (isa<ConstantExpr>(DimTileSizeExpr))
14192 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14213 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14217 CurScope, {}, BO_LE,
14218 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14221 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14227 for (
int I = NumLoops - 1; I >= 0; --I) {
14230 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters[0]);
14232 Stmt *LoopStmt = LoopStmts[I];
14237 auto MakeTileIVRef = [&
SemaRef = this->
SemaRef, &TileIndVars, I, IVTy,
14240 OrigCntVar->getExprLoc());
14242 auto MakeFloorIVRef = [&
SemaRef = this->
SemaRef, &FloorIndVars, I, IVTy,
14245 OrigCntVar->getExprLoc());
14252 Decl *CounterDecl = TileIndVars[I];
14255 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14263 MakeFloorIVRef(), MakeDimTileSize(I));
14268 NumIterations, EndOfTile.
get());
14273 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
14274 if (!MinTileAndIterSpace.
isUsable())
14278 MakeTileIVRef(), MinTileAndIterSpace.
get());
14284 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeTileIVRef());
14305 BodyParts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14306 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14307 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14308 BodyParts.push_back(Inner);
14310 Inner->getBeginLoc(), Inner->getEndLoc());
14311 Inner =
new (Context)
14318 for (
int I = NumLoops - 1; I >= 0; --I) {
14319 auto &LoopHelper = LoopHelpers[I];
14320 Expr *NumIterations = LoopHelper.NumIterations;
14321 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14327 auto MakeFloorIVRef = [&
SemaRef = this->
SemaRef, &FloorIndVars, I, IVTy,
14338 Decl *CounterDecl = FloorIndVars[I];
14348 MakeFloorIVRef(), NumIterations);
14355 MakeFloorIVRef(), MakeDimTileSize(I));
14359 Inner =
new (Context)
14361 IncrStmt.
get(), Inner, LoopHelper.Init->getBeginLoc(),
14362 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14381 {OMPC_partial, OMPC_full}))
14385 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14387 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14388 assert(!(FullClause && PartialClause) &&
14389 "mutual exclusivity must have been checked before");
14391 constexpr unsigned NumLoops = 1;
14392 Stmt *Body =
nullptr;
14396 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14397 Body, OriginalInits))
14400 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14405 NumGeneratedLoops,
nullptr,
nullptr);
14407 assert(LoopHelpers.size() == NumLoops &&
14408 "Expecting a single-dimensional loop iteration space");
14409 assert(OriginalInits.size() == NumLoops &&
14410 "Expecting a single-dimensional loop iteration space");
14418 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14420 <<
"#pragma omp unroll full";
14428 if (NumGeneratedLoops == 0)
14430 NumGeneratedLoops,
nullptr,
nullptr);
14475 Stmt *LoopStmt =
nullptr;
14480 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14482 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14483 QualType IVTy = IterationVarRef->getType();
14484 assert(LoopHelper.
Counters.size() == 1 &&
14485 "Expecting a single-dimensional loop iteration space");
14486 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14492 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14493 FactorLoc = FactorVal->getExprLoc();
14498 assert(Factor > 0 &&
"Expected positive unroll factor");
14499 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
14511 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14512 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
14513 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
14514 std::string InnerTripCountName =
14515 (Twine(
".unroll_inner.tripcount.") + OrigVarName).str();
14520 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
14526 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14528 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
14534 CaptureVars CopyTransformer(
SemaRef);
14535 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
14558 MakeOuterRef(), MakeFactorExpr());
14563 MakeInnerRef(), EndOfTile.
get());
14568 MakeInnerRef(), MakeNumIterations());
14573 InnerCond1.
get(), InnerCond2.
get());
14579 CurScope, LoopHelper.
Inc->
getExprLoc(), UO_PreInc, MakeInnerRef());
14585 InnerBodyStmts.append(LoopHelper.
Updates.begin(), LoopHelper.
Updates.end());
14586 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14587 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14588 InnerBodyStmts.push_back(Body);
14592 ForStmt *InnerFor =
new (Context)
14593 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
14609 LoopHintAttr *UnrollHintAttr =
14610 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14611 LoopHintAttr::Numeric, MakeFactorExpr());
14628 MakeOuterRef(), MakeNumIterations());
14635 MakeOuterRef(), MakeFactorExpr());
14640 ForStmt *OuterFor =
new (Context)
14641 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
14646 NumGeneratedLoops, OuterFor,
14660 constexpr unsigned NumLoops = 1;
14661 Stmt *Body =
nullptr;
14665 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14666 Body, OriginalInits))
14675 assert(LoopHelpers.size() == NumLoops &&
14676 "Expecting a single-dimensional loop iteration space");
14677 assert(OriginalInits.size() == NumLoops &&
14678 "Expecting a single-dimensional loop iteration space");
14682 Stmt *LoopStmt =
nullptr;
14687 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14689 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.
IterationVarRef);
14690 QualType IVTy = IterationVarRef->getType();
14692 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14705 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14707 ForwardIVName += OrigVarName;
14709 ReversedIVName += OrigVarName;
14742 CaptureVars CopyTransformer(
SemaRef);
14743 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
14751 auto MakeForwardRef = [&
SemaRef = this->
SemaRef, ForwardIVDecl, IVTy,
14758 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14759 ReversedIVDecl->setDeclName(
14767 ForwardIVDecl->
getType(), OrigVarLoc);
14771 if (!
Init.isUsable())
14780 MakeForwardRef(), MakeNumIterations());
14789 UO_PreInc, MakeForwardRef());
14800 MakeNumIterations(), One);
14808 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14816 BodyStmts.reserve(LoopHelper.
Updates.size() + 2 +
14817 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14818 BodyStmts.push_back(InitReversed.
get());
14819 llvm::append_range(BodyStmts, LoopHelper.
Updates);
14820 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14821 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14822 BodyStmts.push_back(Body);
14823 auto *ReversedBody =
14828 auto *ReversedFor =
new (Context)
14849 constexpr size_t NumLoops = 2;
14853 Stmt *Body =
nullptr;
14855 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14856 LoopHelpers, Body, OriginalInits))
14862 NumLoops, AStmt,
nullptr,
nullptr);
14864 assert(LoopHelpers.size() == NumLoops &&
14865 "Expecting loop iteration space dimensionaly to match number of "
14867 assert(OriginalInits.size() == NumLoops &&
14868 "Expecting loop iteration space dimensionaly to match number of "
14872 constexpr uint64_t Permutation[] = {1, 0};
14880 for (
auto I : llvm::seq<int>(NumLoops)) {
14883 assert(LoopHelper.
Counters.size() == 1 &&
14884 "Single-dimensional loop iteration space expected");
14885 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.
Counters.front());
14887 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14893 CaptureVars CopyTransformer(
SemaRef);
14898 Stmt *Inner = Body;
14899 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
14901 uint64_t SourceIdx = Permutation[TargetIdx];
14903 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
14904 assert(SourceHelper.
Counters.size() == 1 &&
14905 "Single-dimensional loop iteration space expected");
14906 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.
Counters.front());
14912 "Expected the logical iteration counter to be an integer");
14914 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14919 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
14921 CopyTransformer.TransformExpr(SourceHelper.
NumIterations));
14928 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
14929 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->
getDecl());
14930 PermutedCntDecl->setDeclName(
14932 PermutedIndVars[TargetIdx] = PermutedCntDecl;
14933 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
14942 if (!Zero.isUsable())
14948 OrigCntVar->getEndLoc());
14958 MakePermutedRef(), MakeNumIterations());
14967 CurScope, SourceHelper.
Inc->
getExprLoc(), UO_PreInc, MakePermutedRef());
14973 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
14974 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14975 BodyParts.push_back(Inner);
14977 Inner->getBeginLoc(), Inner->getEndLoc());
14978 Inner =
new (Context)
ForStmt(
14979 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
14985 NumLoops, AStmt, Inner,
14999 case OMPC_num_threads:
15008 case OMPC_allocator:
15011 case OMPC_collapse:
15017 case OMPC_priority:
15029 case OMPC_novariants:
15032 case OMPC_nocontext:
15047 case OMPC_ompx_dyn_cgroup_mem:
15053 case OMPC_grainsize:
15054 case OMPC_num_tasks:
15058 case OMPC_proc_bind:
15059 case OMPC_schedule:
15061 case OMPC_firstprivate:
15062 case OMPC_lastprivate:
15064 case OMPC_reduction:
15065 case OMPC_task_reduction:
15066 case OMPC_in_reduction:
15070 case OMPC_copyprivate:
15073 case OMPC_mergeable:
15074 case OMPC_threadprivate:
15076 case OMPC_allocate:
15093 case OMPC_dist_schedule:
15094 case OMPC_defaultmap:
15099 case OMPC_use_device_ptr:
15100 case OMPC_use_device_addr:
15101 case OMPC_is_device_ptr:
15102 case OMPC_unified_address:
15103 case OMPC_unified_shared_memory:
15104 case OMPC_reverse_offload:
15105 case OMPC_dynamic_allocators:
15106 case OMPC_atomic_default_mem_order:
15107 case OMPC_device_type:
15109 case OMPC_nontemporal:
15112 case OMPC_severity:
15114 case OMPC_inclusive:
15115 case OMPC_exclusive:
15116 case OMPC_uses_allocators:
15117 case OMPC_affinity:
15120 case OMPC_num_teams:
15121 case OMPC_thread_limit:
15123 llvm_unreachable(
"Clause is not allowed.");
15136 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15137 "Invalid directive with CKind-clause");
15140 if (NameModifier != OMPD_unknown &&
15141 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15142 return OMPD_unknown;
15161 case OMPD_teams_loop:
15162 case OMPD_target_teams_loop:
15166 case OMPD_target_update:
15167 case OMPD_target_enter_data:
15168 case OMPD_target_exit_data:
15174 case OMPC_num_teams:
15175 case OMPC_thread_limit:
15176 case OMPC_ompx_dyn_cgroup_mem:
15177 if (Leafs[0] == OMPD_target)
15178 return OMPD_target;
15181 if (Leafs[0] == OMPD_target ||
15182 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15183 OMPD_target_enter_data, OMPD_target_exit_data},
15187 case OMPC_novariants:
15188 case OMPC_nocontext:
15189 if (DKind == OMPD_dispatch)
15193 if (DKind == OMPD_metadirective)
15194 return OMPD_metadirective;
15197 return OMPD_unknown;
15210 int InnermostIdx = [&]() {
15211 for (
int I = EndIdx - 1; I >= 0; --I) {
15212 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15220 for (
int I = InnermostIdx - 1; I >= 0; --I) {
15225 if (Regions[0] != OMPD_unknown)
15226 return Regions.back();
15228 return OMPD_unknown;
15233 for (
int I = 0,
E = Leafs.size(); I !=
E; ++I) {
15234 if (Leafs[I] == Dir)
15240 int End = NameModifier == OMPD_unknown ? Leafs.size()
15241 : GetLeafIndex(NameModifier);
15242 return GetEnclosingRegion(End, CKind);
15245 return OMPD_unknown;
15253 Stmt *HelperValStmt =
nullptr;
15256 !
Condition->isInstantiationDependent() &&
15257 !
Condition->containsUnexpandedParameterPack()) {
15262 ValExpr = Val.
get();
15266 DKind, OMPC_if,
getLangOpts().OpenMP, NameModifier);
15267 if (CaptureRegion != OMPD_unknown &&
15270 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15271 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15277 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15278 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15286 Stmt *HelperValStmt =
nullptr;
15289 !
Condition->isInstantiationDependent() &&
15290 !
Condition->containsUnexpandedParameterPack()) {
15300 if (CaptureRegion != OMPD_unknown &&
15303 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15304 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15310 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15321 IntConvertDiagnoser()
15322 : ICEConvertDiagnoser(
false,
false,
true) {}
15325 return S.
Diag(
Loc, diag::err_omp_not_integral) <<
T;
15329 return S.
Diag(
Loc, diag::err_omp_incomplete_type) <<
T;
15334 return S.
Diag(
Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
15343 return S.
Diag(
Loc, diag::err_omp_ambiguous_conversion) <<
T;
15352 llvm_unreachable(
"conversion functions are permitted");
15354 } ConvertDiagnoser;
15360 bool StrictlyPositive,
bool BuildCapture =
false,
15363 Stmt **HelperValStmt =
nullptr) {
15369 if (
Value.isInvalid())
15372 ValExpr =
Value.get();
15374 if (std::optional<llvm::APSInt>
Result =
15376 if (
Result->isSigned() &&
15377 !((!StrictlyPositive &&
Result->isNonNegative()) ||
15378 (StrictlyPositive &&
Result->isStrictlyPositive()))) {
15379 SemaRef.
Diag(
Loc, diag::err_omp_negative_expression_in_clause)
15380 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15389 if (*CaptureRegion != OMPD_unknown &&
15392 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15393 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15404 Expr *ValExpr = NumThreads;
15405 Stmt *HelperValStmt =
nullptr;
15416 if (CaptureRegion != OMPD_unknown &&
15419 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15420 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
15425 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15430 bool SuppressExprDiags) {
15439 if (SuppressExprDiags) {
15443 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
15446 llvm_unreachable(
"Diagnostic suppressed");
15458 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
15459 (!StrictlyPositive && !
Result.isNonNegative())) {
15461 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15465 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !
Result.isPowerOf2()) {
15470 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
15472 else if (CKind == OMPC_ordered)
15507 DSAStackTy *Stack) {
15508 if (!Stack->getOMPAllocatorHandleT().isNull())
15515 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15516 <<
"omp_allocator_handle_t";
15521 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15524 bool ErrorFound =
false;
15525 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15526 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
15527 StringRef Allocator =
15528 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15530 auto *VD = dyn_cast_or_null<ValueDecl>(
15550 Stack->setAllocator(AllocatorKind, Res.
get());
15553 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15554 <<
"omp_allocator_handle_t";
15571 if (Allocator.isInvalid())
15574 Allocator.get(),
DSAStack->getOMPAllocatorHandleT(),
15577 if (Allocator.isInvalid())
15603 Expr *NumForLoops) {
15609 if (NumForLoops && LParenLoc.
isValid()) {
15614 NumForLoops = NumForLoopsResult.
get();
15616 NumForLoops =
nullptr;
15620 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
15621 StartLoc, LParenLoc, EndLoc);
15622 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
15633 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15635 case OMPC_proc_bind:
15637 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15639 case OMPC_atomic_default_mem_order:
15642 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15646 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15650 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15654 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15658 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15660 case OMPC_severity:
15663 LParenLoc, EndLoc);
15667 case OMPC_num_threads:
15671 case OMPC_allocator:
15672 case OMPC_collapse:
15673 case OMPC_schedule:
15675 case OMPC_firstprivate:
15676 case OMPC_lastprivate:
15678 case OMPC_reduction:
15679 case OMPC_task_reduction:
15680 case OMPC_in_reduction:
15684 case OMPC_copyprivate:
15688 case OMPC_mergeable:
15689 case OMPC_threadprivate:
15690 case OMPC_allocate:
15707 case OMPC_num_teams:
15708 case OMPC_thread_limit:
15709 case OMPC_priority:
15710 case OMPC_grainsize:
15712 case OMPC_num_tasks:
15714 case OMPC_dist_schedule:
15715 case OMPC_defaultmap:
15720 case OMPC_use_device_ptr:
15721 case OMPC_use_device_addr:
15722 case OMPC_is_device_ptr:
15723 case OMPC_has_device_addr:
15724 case OMPC_unified_address:
15725 case OMPC_unified_shared_memory:
15726 case OMPC_reverse_offload:
15727 case OMPC_dynamic_allocators:
15728 case OMPC_device_type:
15730 case OMPC_nontemporal:
15732 case OMPC_novariants:
15733 case OMPC_nocontext:
15735 case OMPC_inclusive:
15736 case OMPC_exclusive:
15737 case OMPC_uses_allocators:
15738 case OMPC_affinity:
15742 llvm_unreachable(
"Clause is not allowed.");
15751 llvm::raw_svector_ostream Out(Buffer);
15752 unsigned Skipped = Exclude.size();
15753 for (
unsigned I =
First; I <
Last; ++I) {
15754 if (llvm::is_contained(Exclude, I)) {
15759 if (I + Skipped + 2 ==
Last)
15761 else if (I + Skipped + 1 !=
Last)
15764 return std::string(Out.str());
15772 if (Kind == OMP_DEFAULT_unknown) {
15773 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15775 unsigned(OMP_DEFAULT_unknown))
15776 << getOpenMPClauseName(OMPC_default);
15781 case OMP_DEFAULT_none:
15782 DSAStack->setDefaultDSANone(KindKwLoc);
15784 case OMP_DEFAULT_shared:
15785 DSAStack->setDefaultDSAShared(KindKwLoc);
15787 case OMP_DEFAULT_firstprivate:
15788 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15790 case OMP_DEFAULT_private:
15791 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15794 llvm_unreachable(
"DSA unexpected in OpenMP default clause");
15806 if (Kind == OMP_PROC_BIND_unknown) {
15807 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15809 unsigned(OMP_PROC_BIND_master),
15812 ? OMP_PROC_BIND_primary
15813 : OMP_PROC_BIND_spread) +
15815 << getOpenMPClauseName(OMPC_proc_bind);
15818 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
15819 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15821 unsigned(OMP_PROC_BIND_master),
15823 unsigned(OMP_PROC_BIND_spread) + 1)
15824 << getOpenMPClauseName(OMPC_proc_bind);
15833 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15835 OMPC_atomic_default_mem_order, 0,
15837 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15841 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15850 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15853 << getOpenMPClauseName(OMPC_at);
15857 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15866 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15869 << getOpenMPClauseName(OMPC_severity);
15880 assert(ME &&
"NULL expr in Message clause");
15881 if (!isa<StringLiteral>(ME)) {
15883 << getOpenMPClauseName(OMPC_message);
15894 if (Kind != OMPC_ORDER_concurrent ||
15899 "OMPC_ORDER_unknown not greater than 0");
15901 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
15905 << getOpenMPClauseName(OMPC_order);
15910 Diag(MLoc, diag::err_omp_unexpected_clause_value)
15914 << getOpenMPClauseName(OMPC_order);
15916 DSAStack->setRegionHasOrderConcurrent(
true);
15919 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
15920 DSAStack->getCurScope()->setFlags(existingFlags |
15926 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
15935 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
15937 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
15938 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
15940 Except.push_back(OMPC_DEPEND_inoutset);
15941 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15944 << getOpenMPClauseName(OMPC_update);
15948 KindKwLoc, Kind, EndLoc);
15957 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
15967 QualType SizeTy = SizeExpr->getType();
15996 if (!SizeExpr->isInstantiationDependent() && !IsValid)
15997 SizeExpr =
nullptr;
16001 SanitizedSizeExprs);
16017 FactorExpr, OMPC_partial,
true);
16020 FactorExpr = FactorResult.
get();
16035 LParenLoc, EndLoc);
16045 case OMPC_schedule:
16046 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16047 assert(Argument.size() == NumberOfElements &&
16048 ArgumentLoc.size() == NumberOfElements);
16053 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16054 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16057 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16059 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16062 case OMPC_dist_schedule:
16065 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16067 case OMPC_defaultmap:
16068 enum { Modifier, DefaultmapKind };
16072 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16076 enum { OrderModifier, OrderKind };
16080 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16083 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16086 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16088 case OMPC_grainsize:
16089 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16090 "Modifier for grainsize clause and its location are expected.");
16093 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16095 case OMPC_num_tasks:
16096 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16097 "Modifier for num_tasks clause and its location are expected.");
16100 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16103 case OMPC_num_threads:
16107 case OMPC_allocator:
16108 case OMPC_collapse:
16110 case OMPC_proc_bind:
16112 case OMPC_firstprivate:
16113 case OMPC_lastprivate:
16115 case OMPC_reduction:
16116 case OMPC_task_reduction:
16117 case OMPC_in_reduction:
16121 case OMPC_copyprivate:
16125 case OMPC_mergeable:
16126 case OMPC_threadprivate:
16127 case OMPC_allocate:
16144 case OMPC_num_teams:
16145 case OMPC_thread_limit:
16146 case OMPC_priority:
16153 case OMPC_use_device_ptr:
16154 case OMPC_use_device_addr:
16155 case OMPC_is_device_ptr:
16156 case OMPC_has_device_addr:
16157 case OMPC_unified_address:
16158 case OMPC_unified_shared_memory:
16159 case OMPC_reverse_offload:
16160 case OMPC_dynamic_allocators:
16161 case OMPC_atomic_default_mem_order:
16162 case OMPC_device_type:
16164 case OMPC_nontemporal:
16166 case OMPC_severity:
16169 case OMPC_novariants:
16170 case OMPC_nocontext:
16172 case OMPC_inclusive:
16173 case OMPC_exclusive:
16174 case OMPC_uses_allocators:
16175 case OMPC_affinity:
16179 llvm_unreachable(
"Clause is not allowed.");
16190 Excluded.push_back(M2);
16191 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16192 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16193 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16194 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16195 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16200 << getOpenMPClauseName(OMPC_schedule);
16218 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16219 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16220 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16221 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16222 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16228 std::string Values;
16238 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16239 << Values << getOpenMPClauseName(OMPC_schedule);
16247 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16248 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16249 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16250 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16251 diag::err_omp_schedule_nonmonotonic_static);
16254 Expr *ValExpr = ChunkSize;
16255 Stmt *HelperValStmt =
nullptr;
16266 ValExpr = Val.
get();
16271 if (std::optional<llvm::APSInt>
Result =
16273 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
16274 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16279 DSAStack->getCurrentDirective(), OMPC_schedule,
16283 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16284 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16292 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16309 case OMPC_mergeable:
16357 case OMPC_unified_address:
16360 case OMPC_unified_shared_memory:
16363 case OMPC_reverse_offload:
16366 case OMPC_dynamic_allocators:
16380 case OMPC_ompx_bare:
16385 case OMPC_num_threads:
16389 case OMPC_allocator:
16390 case OMPC_collapse:
16391 case OMPC_schedule:
16393 case OMPC_firstprivate:
16394 case OMPC_lastprivate:
16396 case OMPC_reduction:
16397 case OMPC_task_reduction:
16398 case OMPC_in_reduction:
16402 case OMPC_copyprivate:
16404 case OMPC_proc_bind:
16405 case OMPC_threadprivate:
16406 case OMPC_allocate:
16412 case OMPC_num_teams:
16413 case OMPC_thread_limit:
16414 case OMPC_priority:
16415 case OMPC_grainsize:
16416 case OMPC_num_tasks:
16418 case OMPC_dist_schedule:
16419 case OMPC_defaultmap:
16424 case OMPC_use_device_ptr:
16425 case OMPC_use_device_addr:
16426 case OMPC_is_device_ptr:
16427 case OMPC_has_device_addr:
16428 case OMPC_atomic_default_mem_order:
16429 case OMPC_device_type:
16431 case OMPC_nontemporal:
16434 case OMPC_severity:
16436 case OMPC_novariants:
16437 case OMPC_nocontext:
16439 case OMPC_inclusive:
16440 case OMPC_exclusive:
16441 case OMPC_uses_allocators:
16442 case OMPC_affinity:
16444 case OMPC_ompx_dyn_cgroup_mem:
16446 llvm_unreachable(
"Clause is not allowed.");
16505 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16586 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16587 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
16588 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16589 <<
Expected << getOpenMPDirectiveName(OMPD_interop);
16602 bool HasInitClause =
false;
16603 bool IsTargetSync =
false;
16607 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
16608 HasInitClause =
true;
16609 if (InitClause->getIsTargetSync())
16610 IsTargetSync =
true;
16611 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
16615 if (DependClause && HasInitClause && !IsTargetSync) {
16616 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16630 if (ClauseKind == OMPC_init) {
16631 auto *
E = cast<OMPInitClause>(
C)->getInteropVar();
16633 }
else if (ClauseKind == OMPC_use) {
16634 auto *
E = cast<OMPUseClause>(
C)->getInteropVar();
16636 }
else if (ClauseKind == OMPC_destroy) {
16637 auto *
E = cast<OMPDestroyClause>(
C)->getInteropVar();
16642 if (!InteropVars.insert(
DeclResult.first).second) {
16643 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16659 Expr *RefExpr = InteropVarExpr;
16662 false,
"omp_interop_t");
16673 bool HasError =
false;
16679 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
16680 InteropType =
QualType(TD->getTypeForDecl(), 0);
16689 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
16690 <<
"omp_interop_t";
16696 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16702 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16704 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
16726 if (isa<StringLiteral>(
E))
16733 StartLoc, LParenLoc, VarLoc, EndLoc);
16746 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16755 DSAStack->getCurrentDirective() == OMPD_depobj) {
16756 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16757 << getOpenMPClauseName(OMPC_destroy)
16758 << getOpenMPDirectiveName(OMPD_depobj);
16774 Stmt *HelperValStmt =
nullptr;
16777 !
Condition->isInstantiationDependent() &&
16778 !
Condition->containsUnexpandedParameterPack()) {
16788 if (CaptureRegion != OMPD_unknown &&
16791 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16792 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16798 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16806 Stmt *HelperValStmt =
nullptr;
16809 !
Condition->isInstantiationDependent() &&
16810 !
Condition->containsUnexpandedParameterPack()) {
16820 if (CaptureRegion != OMPD_unknown &&
16823 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16824 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16830 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16837 Expr *ValExpr = ThreadID;
16838 Stmt *HelperValStmt =
nullptr;
16843 if (CaptureRegion != OMPD_unknown &&
16846 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16847 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16852 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16863 int ExtraModifier =
Data.ExtraModifier;
16870 case OMPC_firstprivate:
16873 case OMPC_lastprivate:
16875 "Unexpected lastprivate modifier.");
16878 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
16883 case OMPC_reduction:
16885 "Unexpected lastprivate modifier.");
16888 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
16889 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
16891 case OMPC_task_reduction:
16893 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16894 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
16896 case OMPC_in_reduction:
16898 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16899 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
16903 "Unexpected linear modifier.");
16905 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
16907 ColonLoc,
Data.StepModifierLoc, EndLoc);
16911 LParenLoc, ColonLoc, EndLoc);
16916 case OMPC_copyprivate:
16924 "Unexpected depend modifier.");
16927 ColonLoc,
Data.OmpAllMemoryLoc},
16928 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
16932 "Unexpected map modifier.");
16934 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
16935 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
16937 ExtraModifierLoc, ColonLoc, VarList, Locs);
16942 Data.ReductionOrMapperIdScopeSpec,
16943 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
16947 Data.ReductionOrMapperIdScopeSpec,
16948 Data.ReductionOrMapperId, ColonLoc, VarList,
16951 case OMPC_use_device_ptr:
16954 case OMPC_use_device_addr:
16957 case OMPC_is_device_ptr:
16960 case OMPC_has_device_addr:
16963 case OMPC_allocate:
16965 LParenLoc, ColonLoc, EndLoc);
16967 case OMPC_nontemporal:
16970 case OMPC_inclusive:
16973 case OMPC_exclusive:
16976 case OMPC_affinity:
16978 Data.DepModOrTailExpr, VarList);
16980 case OMPC_doacross:
16983 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
16985 case OMPC_num_teams:
16988 case OMPC_thread_limit:
16994 case OMPC_num_threads:
16998 case OMPC_allocator:
16999 case OMPC_collapse:
17001 case OMPC_proc_bind:
17002 case OMPC_schedule:
17006 case OMPC_mergeable:
17007 case OMPC_threadprivate:
17021 case OMPC_priority:
17022 case OMPC_grainsize:
17024 case OMPC_num_tasks:
17026 case OMPC_dist_schedule:
17027 case OMPC_defaultmap:
17030 case OMPC_unified_address:
17031 case OMPC_unified_shared_memory:
17032 case OMPC_reverse_offload:
17033 case OMPC_dynamic_allocators:
17034 case OMPC_atomic_default_mem_order:
17035 case OMPC_device_type:
17039 case OMPC_severity:
17042 case OMPC_novariants:
17043 case OMPC_nocontext:
17045 case OMPC_uses_allocators:
17049 llvm_unreachable(
"Clause is not allowed.");
17080 bool IsImplicitClause =
17082 for (
Expr *RefExpr : VarList) {
17083 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
17086 Expr *SimpleRefExpr = RefExpr;
17090 Vars.push_back(RefExpr);
17091 PrivateCopies.push_back(
nullptr);
17098 auto *VD = dyn_cast<VarDecl>(
D);
17104 diag::err_omp_private_incomplete_type))
17106 Type =
Type.getNonReferenceType();
17126 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17127 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17128 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17129 << getOpenMPClauseName(OMPC_private);
17138 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17139 << getOpenMPClauseName(OMPC_private) <<
Type
17140 << getOpenMPDirectiveName(CurrDir);
17141 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17144 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17159 CurrDir == OMPD_target) {
17161 if (
DSAStack->checkMappableExprComponentListsForDecl(
17165 ConflictKind = WhereFoundClauseKind;
17168 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17169 << getOpenMPClauseName(OMPC_private)
17170 << getOpenMPClauseName(ConflictKind)
17171 << getOpenMPDirectiveName(CurrDir);
17190 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17199 auto *FD = dyn_cast<FieldDecl>(
D);
17203 RefExpr->getExprLoc());
17207 if (!IsImplicitClause)
17208 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17210 ? RefExpr->IgnoreParens()
17212 PrivateCopies.push_back(VDPrivateRefExpr);
17219 Vars, PrivateCopies);
17230 bool IsImplicitClause =
17234 for (
Expr *RefExpr : VarList) {
17235 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
17238 Expr *SimpleRefExpr = RefExpr;
17242 Vars.push_back(RefExpr);
17243 PrivateCopies.push_back(
nullptr);
17244 Inits.push_back(
nullptr);
17250 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17252 auto *VD = dyn_cast<VarDecl>(
D);
17258 diag::err_omp_firstprivate_incomplete_type))
17260 Type =
Type.getNonReferenceType();
17270 DSAStackTy::DSAVarData TopDVar;
17271 if (!IsImplicitClause) {
17272 DSAStackTy::DSAVarData DVar =
17284 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17286 DVar.CKind != OMPC_lastprivate) &&
17288 Diag(ELoc, diag::err_omp_wrong_dsa)
17289 << getOpenMPClauseName(DVar.CKind)
17290 << getOpenMPClauseName(OMPC_firstprivate);
17306 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17307 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17308 Diag(ELoc, diag::err_omp_wrong_dsa)
17309 << getOpenMPClauseName(DVar.CKind)
17310 << getOpenMPClauseName(OMPC_firstprivate);
17334 DVar =
DSAStack->getImplicitDSA(
D,
true);
17335 if (DVar.CKind != OMPC_shared &&
17338 DVar.DKind == OMPD_unknown)) {
17339 Diag(ELoc, diag::err_omp_required_access)
17340 << getOpenMPClauseName(OMPC_firstprivate)
17341 << getOpenMPClauseName(OMPC_shared);
17361 return C == OMPC_reduction && !AppliedToPointee;
17369 if (DVar.CKind == OMPC_reduction &&
17373 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17374 << getOpenMPDirectiveName(DVar.DKind);
17390 CurrDir == OMPD_target) {
17392 if (
DSAStack->checkMappableExprComponentListsForDecl(
17397 ConflictKind = WhereFoundClauseKind;
17400 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17401 << getOpenMPClauseName(OMPC_firstprivate)
17402 << getOpenMPClauseName(ConflictKind)
17403 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17413 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17414 << getOpenMPClauseName(OMPC_firstprivate) <<
Type
17415 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17416 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17419 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17428 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17434 Expr *VDInitRefExpr =
nullptr;
17444 ElemType,
".firstprivate.temp");
17459 ".firstprivate.temp");
17461 RefExpr->getExprLoc());
17467 if (IsImplicitClause) {
17468 Diag(RefExpr->getExprLoc(),
17469 diag::note_omp_task_predetermined_firstprivate_here);
17476 RefExpr->getExprLoc());
17479 if (TopDVar.CKind == OMPC_lastprivate) {
17480 Ref = TopDVar.PrivateCopy;
17482 auto *FD = dyn_cast<FieldDecl>(
D);
17487 RefExpr->getExprLoc());
17491 ExprCaptures.push_back(Ref->
getDecl());
17494 if (!IsImplicitClause)
17495 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17497 ? RefExpr->IgnoreParens()
17499 PrivateCopies.push_back(VDPrivateRefExpr);
17500 Inits.push_back(VDInitRefExpr);
17507 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17516 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
17517 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17520 << getOpenMPClauseName(OMPC_lastprivate);
17530 for (
Expr *RefExpr : VarList) {
17531 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17534 Expr *SimpleRefExpr = RefExpr;
17538 Vars.push_back(RefExpr);
17539 SrcExprs.push_back(
nullptr);
17540 DstExprs.push_back(
nullptr);
17541 AssignmentOps.push_back(
nullptr);
17548 auto *VD = dyn_cast<VarDecl>(
D);
17554 diag::err_omp_lastprivate_incomplete_type))
17556 Type =
Type.getNonReferenceType();
17573 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17574 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17577 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17591 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17592 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17594 DVar.CKind != OMPC_firstprivate) &&
17595 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
17596 Diag(ELoc, diag::err_omp_wrong_dsa)
17597 << getOpenMPClauseName(DVar.CKind)
17598 << getOpenMPClauseName(OMPC_lastprivate);
17609 DSAStackTy::DSAVarData TopDVar = DVar;
17613 DVar =
DSAStack->getImplicitDSA(
D,
true);
17614 if (DVar.CKind != OMPC_shared) {
17615 Diag(ELoc, diag::err_omp_required_access)
17616 << getOpenMPClauseName(OMPC_lastprivate)
17617 << getOpenMPClauseName(OMPC_shared);
17633 Type.getUnqualifiedType(),
".lastprivate.src",
17644 PseudoDstExpr, PseudoSrcExpr);
17654 if (TopDVar.CKind == OMPC_firstprivate) {
17655 Ref = TopDVar.PrivateCopy;
17659 ExprCaptures.push_back(Ref->
getDecl());
17661 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17669 SimpleRefExpr, RefRes.
get());
17672 ExprPostUpdates.push_back(
17676 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17678 ? RefExpr->IgnoreParens()
17680 SrcExprs.push_back(PseudoSrcExpr);
17681 DstExprs.push_back(PseudoDstExpr);
17682 AssignmentOps.push_back(AssignmentOp.
get());
17689 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17690 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17700 for (
Expr *RefExpr : VarList) {
17701 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17704 Expr *SimpleRefExpr = RefExpr;
17708 Vars.push_back(RefExpr);
17714 auto *VD = dyn_cast<VarDecl>(
D);
17722 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17723 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17725 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17726 << getOpenMPClauseName(OMPC_shared);
17735 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17737 ? RefExpr->IgnoreParens()
17749class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
17754 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
17755 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
17756 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17758 if (DVar.CKind != OMPC_unknown)
17760 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17767 return DVarPrivate.CKind != OMPC_unknown;
17771 bool VisitStmt(
Stmt *S) {
17772 for (
Stmt *Child : S->children()) {
17773 if (Child && Visit(Child))
17778 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17785class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
17792 : BaseTransform(SemaRef),
Field(
FieldDecl), CapturedExpr(nullptr) {}
17796 E->getMemberDecl() == Field) {
17798 return CapturedExpr;
17800 return BaseTransform::TransformMemberExpr(
E);
17802 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
17806template <
typename T,
typename U>
17809 for (
U &
Set : Lookups) {
17810 for (
auto *
D :
Set) {
17811 if (
T Res = Gen(cast<ValueDecl>(
D)))
17826 auto ND = cast<NamedDecl>(RD);
17844 AssociatedClasses);
17857 for (
auto *NS : AssociatedNamespaces) {
17870 for (
auto *
D : R) {
17871 auto *Underlying =
D;
17872 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
17873 Underlying = USD->getTargetDecl();
17875 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
17876 !isa<OMPDeclareMapperDecl>(Underlying))
17883 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
17884 Underlying = USD->getTargetDecl();
17886 Lookups.emplace_back();
17887 Lookups.back().addDecl(Underlying);
17907 S = S->getParent();
17908 }
while (S && !S->isDeclScope(
D));
17910 S = S->getParent();
17911 Lookups.emplace_back();
17912 Lookups.back().append(Lookup.
begin(), Lookup.
end());
17915 }
else if (
auto *ULE =
17916 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
17918 Decl *PrevD =
nullptr;
17922 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(
D))
17923 Lookups.back().addDecl(DRD);
17930 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
17931 return !D->isInvalidDecl() &&
17932 (D->getType()->isDependentType() ||
17933 D->getType()->isInstantiationDependentType() ||
17934 D->getType()->containsUnexpandedParameterPack());
17947 true, ResSet.
begin(), ResSet.
end(),
false,
17969 TyRec->getDecl()->getDefinition()) {
17972 if (Lookup.
empty()) {
17973 Lookups.emplace_back();
17974 Lookups.back().append(Lookup.
begin(), Lookup.
end());
17981 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
17991 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18015 if (ReductionIdScopeSpec.
isSet()) {
18016 SemaRef.
Diag(
Loc, diag::err_omp_not_resolved_reduction_identifier)
18025struct ReductionData {
18050 unsigned RedModifier = 0;
18051 ReductionData() =
delete;
18053 ReductionData(
unsigned Size,
unsigned Modifier = 0) : RedModifier(Modifier) {
18054 Vars.reserve(Size);
18055 Privates.reserve(Size);
18056 LHSs.reserve(Size);
18057 RHSs.reserve(Size);
18058 ReductionOps.reserve(Size);
18059 if (RedModifier == OMPC_REDUCTION_inscan) {
18060 InscanCopyOps.reserve(Size);
18061 InscanCopyArrayTemps.reserve(Size);
18062 InscanCopyArrayElems.reserve(Size);
18064 TaskgroupDescriptors.reserve(Size);
18065 ExprCaptures.reserve(Size);
18066 ExprPostUpdates.reserve(Size);
18070 void push(
Expr *Item,
Expr *ReductionOp) {
18071 Vars.emplace_back(Item);
18072 Privates.emplace_back(
nullptr);
18073 LHSs.emplace_back(
nullptr);
18074 RHSs.emplace_back(
nullptr);
18075 ReductionOps.emplace_back(ReductionOp);
18076 TaskgroupDescriptors.emplace_back(
nullptr);
18077 if (RedModifier == OMPC_REDUCTION_inscan) {
18078 InscanCopyOps.push_back(
nullptr);
18079 InscanCopyArrayTemps.push_back(
nullptr);
18080 InscanCopyArrayElems.push_back(
nullptr);
18085 Expr *TaskgroupDescriptor,
Expr *CopyOp,
Expr *CopyArrayTemp,
18086 Expr *CopyArrayElem) {
18087 Vars.emplace_back(Item);
18088 Privates.emplace_back(Private);
18089 LHSs.emplace_back(LHS);
18090 RHSs.emplace_back(RHS);
18091 ReductionOps.emplace_back(ReductionOp);
18092 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18093 if (RedModifier == OMPC_REDUCTION_inscan) {
18094 InscanCopyOps.push_back(CopyOp);
18095 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18096 InscanCopyArrayElems.push_back(CopyArrayElem);
18098 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
18099 CopyArrayElem ==
nullptr &&
18100 "Copy operation must be used for inscan reductions only.");
18110 if (Length ==
nullptr) {
18117 SingleElement =
true;
18118 ArraySizes.push_back(llvm::APSInt::get(1));
18121 if (!Length->EvaluateAsInt(
Result, Context))
18124 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18125 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18126 ArraySizes.push_back(ConstantLengthValue);
18134 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
18135 Length = TempOASE->getLength();
18136 if (Length ==
nullptr) {
18143 ArraySizes.push_back(llvm::APSInt::get(1));
18146 if (!Length->EvaluateAsInt(
Result, Context))
18149 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18150 if (ConstantLengthValue.getSExtValue() != 1)
18153 ArraySizes.push_back(ConstantLengthValue);
18155 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18159 if (!SingleElement) {
18160 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
18162 ArraySizes.push_back(llvm::APSInt::get(1));
18163 Base = TempASE->getBase()->IgnoreParenImpCasts();
18175 return BO_AddAssign;
18177 return BO_MulAssign;
18179 return BO_AndAssign;
18181 return BO_OrAssign;
18183 return BO_XorAssign;
18239 case OO_Array_Delete:
18248 case OO_GreaterEqual:
18250 case OO_MinusEqual:
18252 case OO_SlashEqual:
18253 case OO_PercentEqual:
18254 case OO_CaretEqual:
18258 case OO_GreaterGreater:
18259 case OO_LessLessEqual:
18260 case OO_GreaterGreaterEqual:
18261 case OO_EqualEqual:
18262 case OO_ExclaimEqual:
18265 case OO_MinusMinus:
18271 case OO_Conditional:
18274 llvm_unreachable(
"Unexpected reduction identifier");
18277 if (II->isStr(
"max"))
18279 else if (II->isStr(
"min"))
18287 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
18288 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18291 if (ReductionIdScopeSpec.
isValid())
18297 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18298 bool FirstIter =
true;
18299 for (
Expr *RefExpr : VarList) {
18300 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
18308 if (!FirstIter && IR != ER)
18313 Expr *SimpleRefExpr = RefExpr;
18322 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18323 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18324 Expr *ReductionOp =
nullptr;
18326 (DeclareReductionRef.
isUnset() ||
18327 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get())))
18328 ReductionOp = DeclareReductionRef.
get();
18330 RD.push(RefExpr, ReductionOp);
18336 Expr *TaskgroupDescriptor =
nullptr;
18338 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18339 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18341 Type = ASE->getType().getNonReferenceType();
18346 Type = ATy->getElementType();
18349 Type =
Type.getNonReferenceType();
18353 auto *VD = dyn_cast<VarDecl>(
D);
18359 diag::err_omp_reduction_incomplete_type))
18365 false, ASE || OASE))
18372 if (!ASE && !OASE) {
18374 VarDecl *VDDef = VD->getDefinition();
18376 DSARefChecker Check(Stack);
18377 if (Check.Visit(VDDef->
getInit())) {
18378 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18379 << getOpenMPClauseName(ClauseKind) << ERange;
18397 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18398 if (DVar.CKind == OMPC_reduction) {
18399 S.
Diag(ELoc, diag::err_omp_once_referenced)
18400 << getOpenMPClauseName(ClauseKind);
18402 S.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18405 if (DVar.CKind != OMPC_unknown) {
18406 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18407 << getOpenMPClauseName(DVar.CKind)
18408 << getOpenMPClauseName(OMPC_reduction);
18420 DVar = Stack->getImplicitDSA(
D,
true);
18421 if (DVar.CKind != OMPC_shared) {
18422 S.
Diag(ELoc, diag::err_omp_required_access)
18423 << getOpenMPClauseName(OMPC_reduction)
18424 << getOpenMPClauseName(OMPC_shared);
18432 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18433 if (DVar.CKind == OMPC_threadprivate) {
18434 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18435 << getOpenMPClauseName(DVar.CKind)
18436 << getOpenMPClauseName(OMPC_reduction);
18446 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18447 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18451 (DeclareReductionRef.
isUnset() ||
18452 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get()))) {
18453 RD.push(RefExpr, DeclareReductionRef.
get());
18456 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
18460 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18461 <<
Type << ReductionIdRange;
18464 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18465 <<
Type << ReductionIdRange;
18477 if (DeclareReductionRef.
isUnset()) {
18478 if ((BOK == BO_GT || BOK == BO_LT) &&
18481 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18482 << getOpenMPClauseName(ClauseKind) << S.
getLangOpts().CPlusPlus;
18483 if (!ASE && !OASE) {
18484 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18487 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18492 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18494 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18495 << getOpenMPClauseName(ClauseKind);
18496 if (!ASE && !OASE) {
18497 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18500 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18507 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
18516 bool ConstantLengthOASE =
false;
18518 bool SingleElement;
18521 Context, OASE, SingleElement, ArraySizes);
18524 if (ConstantLengthOASE && !SingleElement) {
18525 for (llvm::APSInt &Size : ArraySizes)
18532 if ((OASE && !ConstantLengthOASE) ||
18534 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18537 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18538 S.
Diag(ELoc, diag::note_vla_unsupported);
18541 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18542 S.
targetDiag(ELoc, diag::note_vla_unsupported);
18555 }
else if (!ASE && !OASE &&
18557 PrivateTy =
D->getType().getNonReferenceType();
18563 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
18568 if (DeclareReductionRef.
isUsable()) {
18570 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18571 if (DRD->getInitializer()) {
18597 Type = ComplexTy->getElementType();
18599 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18606 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18628 llvm::APInt InitValue =
18629 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18630 : llvm::APInt::getMinValue(Size)
18631 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18632 : llvm::APInt::getMaxValue(Size);
18643 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18674 llvm_unreachable(
"Unexpected reduction operation");
18683 }
else if (!
Init) {
18693 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18694 <<
Type << ReductionIdRange;
18695 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18698 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18704 if (DeclareReductionRef.
isUsable()) {
18709 if (!BasePath.empty()) {
18713 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
18716 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
18720 QualType Params[] = {PtrRedTy, PtrRedTy};
18735 CombBOK, LHSDRE, RHSDRE);
18742 if (BOK != BO_LT && BOK != BO_GT) {
18745 BO_Assign, LHSDRE, ReductionOp.
get());
18747 auto *ConditionalOp =
new (Context)
18752 BO_Assign, LHSDRE, ConditionalOp);
18765 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18766 if (ClauseKind == OMPC_reduction &&
18767 RD.RedModifier == OMPC_REDUCTION_inscan) {
18769 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18779 if (Stack->getCurrentDirective() == OMPD_simd ||
18817 if (ClauseKind == OMPC_in_reduction) {
18820 const Expr *ParentReductionOp =
nullptr;
18821 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
18822 DSAStackTy::DSAVarData ParentBOKDSA =
18823 Stack->getTopMostTaskgroupReductionData(
D, ParentSR, ParentBOK,
18825 DSAStackTy::DSAVarData ParentReductionOpDSA =
18826 Stack->getTopMostTaskgroupReductionData(
18827 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
18828 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
18829 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
18830 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
18831 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
18832 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
18833 bool EmitError =
true;
18834 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
18835 llvm::FoldingSetNodeID RedId, ParentRedId;
18836 ParentReductionOp->
Profile(ParentRedId, Context,
true);
18837 DeclareReductionRef.
get()->
Profile(RedId, Context,
18839 EmitError = RedId != ParentRedId;
18843 diag::err_omp_reduction_identifier_mismatch)
18844 << ReductionIdRange << RefExpr->getSourceRange();
18846 diag::note_omp_previous_reduction_identifier)
18848 << (IsParentBOK ? ParentBOKDSA.RefExpr
18849 : ParentReductionOpDSA.RefExpr)
18850 ->getSourceRange();
18854 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
18861 TransformExprToCaptures RebuildToCapture(S,
D);
18863 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
18864 Ref = RebuildToCapture.getCapturedExpr();
18869 RD.ExprCaptures.emplace_back(Ref->
getDecl());
18875 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18880 Stack->getCurrentDirective() == OMPD_taskgroup) {
18881 S.
Diag(RefExpr->getExprLoc(),
18882 diag::err_omp_reduction_non_addressable_expression)
18883 << RefExpr->getSourceRange();
18886 RD.ExprPostUpdates.emplace_back(
18893 unsigned Modifier = RD.RedModifier;
18896 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
18897 Modifier = OMPC_REDUCTION_task;
18898 Stack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
18900 if (Modifier == OMPC_REDUCTION_task &&
18901 (CurrDir == OMPD_taskgroup ||
18905 if (DeclareReductionRef.
isUsable())
18906 Stack->addTaskgroupReductionData(
D, ReductionIdRange,
18907 DeclareReductionRef.
get());
18909 Stack->addTaskgroupReductionData(
D, ReductionIdRange, BOK);
18911 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
18912 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
18913 TempArrayElem.
get());
18915 return RD.Vars.empty();
18925 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
18928 << getOpenMPClauseName(OMPC_reduction);
18936 if (Modifier == OMPC_REDUCTION_inscan &&
18937 (
DSAStack->getCurrentDirective() != OMPD_for &&
18938 DSAStack->getCurrentDirective() != OMPD_for_simd &&
18939 DSAStack->getCurrentDirective() != OMPD_simd &&
18940 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
18941 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
18942 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
18946 ReductionData RD(VarList.size(), Modifier);
18948 StartLoc, LParenLoc, ColonLoc, EndLoc,
18949 ReductionIdScopeSpec, ReductionId,
18950 UnresolvedReductions, RD))
18954 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
18957 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
18958 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
18968 ReductionData RD(VarList.size());
18970 VarList, StartLoc, LParenLoc, ColonLoc,
18971 EndLoc, ReductionIdScopeSpec, ReductionId,
18972 UnresolvedReductions, RD))
18976 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
18978 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
18988 ReductionData RD(VarList.size());
18990 StartLoc, LParenLoc, ColonLoc, EndLoc,
18991 ReductionIdScopeSpec, ReductionId,
18992 UnresolvedReductions, RD))
18996 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
18998 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19007 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19017 const auto *VD = dyn_cast_or_null<VarDecl>(
D);
19020 diag::err_omp_linear_incomplete_type))
19022 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19024 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19028 Type =
Type.getNonReferenceType();
19035 if (!IsDeclareSimd &&
19040 Type =
Type.getUnqualifiedType().getCanonicalType();
19041 const auto *Ty =
Type.getTypePtrOrNull();
19042 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19043 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
19044 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
19046 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19049 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19072 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19074 LinKind = OMPC_LINEAR_val;
19075 for (
Expr *RefExpr : VarList) {
19076 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19079 Expr *SimpleRefExpr = RefExpr;
19083 Vars.push_back(RefExpr);
19084 Privates.push_back(
nullptr);
19085 Inits.push_back(
nullptr);
19092 auto *VD = dyn_cast<VarDecl>(
D);
19098 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
19099 if (DVar.RefExpr) {
19100 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19101 << getOpenMPClauseName(OMPC_linear);
19108 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19114 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
19123 ExprCaptures.push_back(Ref->
getDecl());
19130 SimpleRefExpr, RefRes.
get());
19133 ExprPostUpdates.push_back(
19138 if (LinKind == OMPC_LINEAR_uval)
19139 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19141 InitExpr = VD ? SimpleRefExpr : Ref;
19147 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19149 ? RefExpr->IgnoreParens()
19151 Privates.push_back(PrivateRef);
19152 Inits.push_back(InitRef);
19158 Expr *StepExpr = Step;
19159 Expr *CalcStepExpr =
nullptr;
19167 StepExpr = Val.
get();
19181 if (std::optional<llvm::APSInt>
Result =
19183 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
19184 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19185 << Vars[0] << (Vars.size() > 1);
19189 CalcStepExpr = CalcStep.
get();
19194 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19195 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19201 Expr *NumIterations,
Sema &SemaRef,
19202 Scope *S, DSAStackTy *Stack) {
19214 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19215 bool HasErrors =
false;
19216 auto CurInit = Clause.
inits().begin();
19217 auto CurPrivate = Clause.
privates().begin();
19222 Expr *SimpleRefExpr = RefExpr;
19223 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19225 if (Res.second || !
D) {
19226 Updates.push_back(
nullptr);
19227 Finals.push_back(
nullptr);
19231 auto &&Info = Stack->isLoopControlVariable(
D);
19238 diag::err_omp_linear_distribute_var_non_loop_iteration);
19239 Updates.push_back(
nullptr);
19240 Finals.push_back(
nullptr);
19244 Expr *InitExpr = *CurInit;
19247 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19249 if (LinKind == OMPC_LINEAR_uval)
19250 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19254 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19261 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19272 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19275 Final = *CurPrivate;
19279 if (!
Update.isUsable() || !Final.isUsable()) {
19280 Updates.push_back(
nullptr);
19281 Finals.push_back(
nullptr);
19282 UsedExprs.push_back(
nullptr);
19285 Updates.push_back(
Update.get());
19286 Finals.push_back(Final.get());
19288 UsedExprs.push_back(SimpleRefExpr);
19294 UsedExprs.push_back(S);
19296 UsedExprs.append(Clause.
varlist_size() + 1 - UsedExprs.size(),
nullptr);
19307 for (
Expr *RefExpr : VarList) {
19308 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19311 Expr *SimpleRefExpr = RefExpr;
19315 Vars.push_back(RefExpr);
19322 auto *VD = dyn_cast<VarDecl>(
D);
19330 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19332 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19335 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19342 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(
D, SimpleRefExpr)) {
19343 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19344 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19345 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19346 << getOpenMPClauseName(OMPC_aligned);
19354 .DefaultFunctionArrayConversion(
19355 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19364 if (Alignment !=
nullptr) {
19369 Alignment = AlignResult.
get();
19375 ColonLoc, EndLoc, Vars, Alignment);
19386 for (
Expr *RefExpr : VarList) {
19387 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
19388 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19390 Vars.push_back(RefExpr);
19391 SrcExprs.push_back(
nullptr);
19392 DstExprs.push_back(
nullptr);
19393 AssignmentOps.push_back(
nullptr);
19402 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19403 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19404 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19405 << 0 << RefExpr->getSourceRange();
19409 Decl *
D = DE->getDecl();
19410 auto *VD = cast<VarDecl>(
D);
19415 Vars.push_back(DE);
19416 SrcExprs.push_back(
nullptr);
19417 DstExprs.push_back(
nullptr);
19418 AssignmentOps.push_back(
nullptr);
19424 if (!
DSAStack->isThreadPrivate(VD)) {
19425 Diag(ELoc, diag::err_omp_required_access)
19426 << getOpenMPClauseName(OMPC_copyin)
19427 << getOpenMPDirectiveName(OMPD_threadprivate);
19451 PseudoDstExpr, PseudoSrcExpr);
19460 DSAStack->addDSA(VD, DE, OMPC_copyin);
19461 Vars.push_back(DE);
19462 SrcExprs.push_back(PseudoSrcExpr);
19463 DstExprs.push_back(PseudoDstExpr);
19464 AssignmentOps.push_back(AssignmentOp.
get());
19471 Vars, SrcExprs, DstExprs, AssignmentOps);
19482 for (
Expr *RefExpr : VarList) {
19483 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19486 Expr *SimpleRefExpr = RefExpr;
19490 Vars.push_back(RefExpr);
19491 SrcExprs.push_back(
nullptr);
19492 DstExprs.push_back(
nullptr);
19493 AssignmentOps.push_back(
nullptr);
19500 auto *VD = dyn_cast<VarDecl>(
D);
19505 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
19506 DSAStackTy::DSAVarData DVar =
19508 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19510 Diag(ELoc, diag::err_omp_wrong_dsa)
19511 << getOpenMPClauseName(DVar.CKind)
19512 << getOpenMPClauseName(OMPC_copyprivate);
19520 if (DVar.CKind == OMPC_unknown) {
19521 DVar =
DSAStack->getImplicitDSA(
D,
false);
19522 if (DVar.CKind == OMPC_shared) {
19523 Diag(ELoc, diag::err_omp_required_access)
19524 << getOpenMPClauseName(OMPC_copyprivate)
19525 <<
"threadprivate or private in the enclosing context";
19534 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19535 << getOpenMPClauseName(OMPC_copyprivate) <<
Type
19536 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
19537 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19540 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19561 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19573 VD ? RefExpr->IgnoreParens()
19575 SrcExprs.push_back(PseudoSrcExpr);
19576 DstExprs.push_back(PseudoDstExpr);
19577 AssignmentOps.push_back(AssignmentOp.
get());
19584 EndLoc, Vars, SrcExprs, DstExprs,
19592 if (VarList.empty())
19601 bool Diagnose =
true) {
19602 QualType OMPDependT = Stack->getOMPDependT();
19603 if (!OMPDependT.
isNull())
19609 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
19612 Stack->setOMPDependT(PT.
get());
19633 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19638 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19648struct DoacrossDataInfoTy {
19654 llvm::APSInt TotalDepCount;
19657static DoacrossDataInfoTy
19664 llvm::APSInt DepCounter(32);
19665 llvm::APSInt TotalDepCount(32);
19667 if (
const Expr *OrderedCountExpr =
19668 Stack->getParentOrderedRegionParam().first) {
19669 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
19670 TotalDepCount.setIsUnsigned(
true);
19673 for (
Expr *RefExpr : VarList) {
19674 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
19675 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19677 Vars.push_back(RefExpr);
19684 if (Stack->getParentOrderedRegionParam().first &&
19685 DepCounter >= TotalDepCount) {
19686 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19700 Vars.push_back(RefExpr);
19706 Expr *LHS = SimpleExpr;
19707 Expr *RHS =
nullptr;
19708 if (
auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19710 OOLoc = BO->getOperatorLoc();
19713 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19714 OOK = OCE->getOperator();
19715 OOLoc = OCE->getOperatorLoc();
19718 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19719 OOK = MCE->getMethodDecl()
19722 .getCXXOverloadedOperator();
19723 OOLoc = MCE->getCallee()->getExprLoc();
19732 Vars.push_back(RefExpr);
19738 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
19739 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19745 RHS, OMPC_depend,
false);
19750 Stack->getParentOrderedRegionParam().first &&
19751 DepCounter != Stack->isParentLoopControlVariable(
D).first) {
19753 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19755 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19758 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19762 OpsOffs.emplace_back(RHS, OOK);
19764 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19767 TotalDepCount > VarList.size() &&
19768 Stack->getParentOrderedRegionParam().first &&
19769 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19770 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19771 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19773 return {Vars, OpsOffs, TotalDepCount};
19782 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
19783 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19784 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19785 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19788 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
19789 DepKind == OMPC_DEPEND_mutexinoutset) {
19790 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19793 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
19794 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19796 DepKind == OMPC_DEPEND_sink ||
19798 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19799 DepKind == OMPC_DEPEND_depobj))) {
19801 OMPC_DEPEND_outallmemory,
19802 OMPC_DEPEND_inoutallmemory};
19804 DSAStack->getCurrentDirective() == OMPD_depobj)
19805 Except.push_back(OMPC_DEPEND_depobj);
19807 Except.push_back(OMPC_DEPEND_inoutset);
19809 ?
"depend modifier(iterator) or "
19811 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19815 << getOpenMPClauseName(OMPC_depend);
19819 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
19821 diag::err_omp_depend_sink_source_with_modifier);
19826 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
19830 llvm::APSInt TotalDepCount(32);
19832 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
19835 Vars = VarOffset.Vars;
19836 OpsOffs = VarOffset.OpsOffs;
19837 TotalDepCount = VarOffset.TotalDepCount;
19839 for (
Expr *RefExpr : VarList) {
19840 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
19841 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19843 Vars.push_back(RefExpr);
19849 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
19850 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
19851 if (OMPDependTFound)
19853 DepKind == OMPC_DEPEND_depobj);
19854 if (DepKind == OMPC_DEPEND_depobj) {
19858 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19859 !RefExpr->isInstantiationDependent() &&
19860 !RefExpr->containsUnexpandedParameterPack() &&
19861 (OMPDependTFound &&
19863 DSAStack->getOMPDependT(), RefExpr->getType()))) {
19864 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19865 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
19868 if (!RefExpr->isLValue()) {
19869 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19870 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
19877 QualType ExprTy = RefExpr->getType().getNonReferenceType();
19878 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
19885 ExprTy = ATy->getElementType();
19891 const Expr *Length = OASE->getLength();
19893 if (Length && !Length->isValueDependent() &&
19895 Result.Val.getInt().isZero()) {
19897 diag::err_omp_depend_zero_length_array_section_not_allowed)
19907 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19908 !RefExpr->isInstantiationDependent() &&
19909 !RefExpr->containsUnexpandedParameterPack() &&
19910 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
19911 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
19913 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19916 << RefExpr->getSourceRange();
19920 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
19921 if (ASE && !ASE->getBase()->isTypeDependent() &&
19924 .getNonReferenceType()
19925 ->isPointerType() &&
19926 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
19927 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19930 << RefExpr->getSourceRange();
19938 RefExpr->IgnoreParenImpCasts());
19940 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
19941 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
19942 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19945 << RefExpr->getSourceRange();
19950 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19954 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
19955 DepKind != OMPC_DEPEND_outallmemory &&
19956 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
19961 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
19962 TotalDepCount.getZExtValue());
19963 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
19964 DSAStack->isParentOrderedRegion())
19965 DSAStack->addDoacrossDependClause(
C, OpsOffs);
19974 "Unexpected device modifier in OpenMP < 50.");
19976 bool ErrorFound =
false;
19978 std::string Values =
19980 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
19981 << Values << getOpenMPClauseName(OMPC_device);
19986 Stmt *HelperValStmt =
nullptr;
19999 if (Modifier == OMPC_DEVICE_ancestor) {
20003 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20011 if (CaptureRegion != OMPD_unknown &&
20014 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20015 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20020 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20021 LParenLoc, ModifierLoc, EndLoc);
20026 bool FullCheck =
true) {
20031 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20041 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20046 if (isa<ArraySubscriptExpr>(
E) ||
20047 (OASE && OASE->getColonLocFirst().isInvalid())) {
20048 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20049 return ATy->getSExtSize() != 1;
20054 assert(OASE &&
"Expecting array section if not an array subscript.");
20055 const Expr *LowerBound = OASE->getLowerBound();
20056 const Expr *Length = OASE->getLength();
20065 llvm::APSInt ConstLowerBound =
Result.Val.getInt();
20066 if (ConstLowerBound.getSExtValue())
20081 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
20089 llvm::APSInt ConstLength =
Result.Val.getInt();
20090 return CATy->getSExtSize() != ConstLength.getSExtValue();
20099 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20103 if (isa<ArraySubscriptExpr>(
E) ||
20104 (OASE && OASE->getColonLocFirst().isInvalid()))
20107 assert(OASE &&
"Expecting array section if not an array subscript.");
20108 const Expr *Length = OASE->getLength();
20114 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20115 return ATy->getSExtSize() != 1;
20125 llvm::APSInt ConstLength =
Result.Val.getInt();
20126 return ConstLength.getSExtValue() != 1;
20165class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
20170 bool IsNonContiguous =
false;
20171 bool NoDiagnose =
false;
20172 const Expr *RelevantExpr =
nullptr;
20173 bool AllowUnitySizeArraySection =
true;
20174 bool AllowWholeSizeArraySection =
true;
20175 bool AllowAnotherPtr =
true;
20179 void emitErrorMsg() {
20181 if (SemaRef.getLangOpts().OpenMP < 50) {
20183 diag::err_omp_expected_named_var_member_or_array_expression)
20186 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20187 << getOpenMPClauseName(CKind) << ERange;
20193 if (!isa<VarDecl>(DRE->
getDecl())) {
20197 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20198 RelevantExpr = DRE;
20200 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
20208 if (isa<CXXThisExpr>(BaseE)) {
20209 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20218 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20234 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20254 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20258 return RelevantExpr || Visit(
E);
20268 AllowUnitySizeArraySection =
false;
20269 AllowWholeSizeArraySection =
false;
20272 Components.emplace_back(ME, FD, IsNonContiguous);
20273 return RelevantExpr || Visit(
E);
20281 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20285 return RelevantExpr || Visit(
E);
20292 AllowWholeSizeArraySection =
false;
20298 !Result.Val.getInt().isZero()) {
20300 diag::err_omp_invalid_map_this_expr);
20302 diag::note_omp_invalid_subscript_on_this_ptr_map);
20304 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20309 Components.emplace_back(AE,
nullptr, IsNonContiguous);
20311 return RelevantExpr || Visit(
E);
20317 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20318 "Array sections cannot be implicitly mapped.");
20332 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20342 if (AllowWholeSizeArraySection) {
20349 if (NotWhole || IsPointer)
20350 AllowWholeSizeArraySection =
false;
20351 }
else if (DKind == OMPD_target_update &&
20352 SemaRef.getLangOpts().OpenMP >= 50) {
20353 if (IsPointer && !AllowAnotherPtr)
20354 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20357 IsNonContiguous =
true;
20358 }
else if (AllowUnitySizeArraySection && NotUnity) {
20364 diag::err_array_section_does_not_specify_contiguous_storage)
20370 AllowAnotherPtr =
false;
20372 if (
const auto *TE = dyn_cast<CXXThisExpr>(
E)) {
20379 diag::err_omp_invalid_map_this_expr);
20381 diag::note_omp_invalid_length_on_this_ptr_mapping);
20385 SemaRef.getASTContext()) &&
20388 diag::err_omp_invalid_map_this_expr);
20390 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20392 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20397 Components.emplace_back(OASE,
nullptr,
false);
20398 return RelevantExpr || Visit(
E);
20404 Components.emplace_back(
E,
nullptr, IsNonContiguous);
20406 return Visit(
Base->IgnoreParenImpCasts());
20410 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
20415 if (!RelevantExpr) {
20417 Components.emplace_back(UO,
nullptr,
false);
20433 Components.emplace_back(BO,
nullptr,
false);
20436 "Either LHS or RHS have base decl inside");
20438 return RelevantExpr || Visit(LE);
20439 return RelevantExpr || Visit(RE);
20442 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20443 RelevantExpr = CTE;
20444 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
20448 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20449 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
20453 Expr *Source =
E->getSourceExpr();
20458 return Visit(Source);
20460 bool VisitStmt(
Stmt *) {
20464 const Expr *getFoundBase()
const {
return RelevantExpr; }
20465 explicit MapBaseChecker(
20469 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20470 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20484 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20488 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20489 (CKind == OMPC_to || CKind == OMPC_from)) {
20490 auto CI = CurComponents.rbegin();
20491 auto CE = CurComponents.rend();
20492 for (; CI != CE; ++CI) {
20494 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20499 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
20503 return Checker.getFoundBase();
20512 bool CurrentRegionOnly,
20523 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
20524 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20525 "Map clause expression with unexpected base!");
20528 bool IsEnclosedByDataEnvironmentExpr =
false;
20529 const Expr *EnclosingExpr =
nullptr;
20531 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20532 VD, CurrentRegionOnly,
20533 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20534 ERange, CKind, &EnclosingExpr,
20538 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
20540 assert(!StackComponents.empty() &&
20541 "Map clause expression with no components!");
20542 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20543 "Map clause expression with unexpected base!");
20547 const Expr *RE = StackComponents.front().getAssociatedExpression();
20553 auto CI = CurComponents.rbegin();
20554 auto CE = CurComponents.rend();
20555 auto SI = StackComponents.rbegin();
20556 auto SE = StackComponents.rend();
20557 for (; CI != CE && SI != SE; ++CI, ++SI) {
20562 if (CurrentRegionOnly &&
20563 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20564 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20565 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20566 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20567 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20568 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20569 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20570 diag::err_omp_multiple_array_items_in_map_clause)
20571 << CI->getAssociatedExpression()->getSourceRange();
20572 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20573 diag::note_used_here)
20574 << SI->getAssociatedExpression()->getSourceRange();
20579 if (CI->getAssociatedExpression()->getStmtClass() !=
20580 SI->getAssociatedExpression()->getStmtClass())
20584 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20590 for (; SI != SE; ++SI) {
20592 if (
const auto *ASE =
20593 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20594 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20595 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
20596 SI->getAssociatedExpression())) {
20597 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20598 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20599 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20600 SI->getAssociatedExpression())) {
20601 Type = OASE->getBase()->getType()->getPointeeType();
20605 SemaRef, SI->getAssociatedExpression(),
Type))
20615 if (CI == CE && SI == SE) {
20616 if (CurrentRegionOnly) {
20617 if (CKind == OMPC_map) {
20618 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20620 assert(CKind == OMPC_to || CKind == OMPC_from);
20621 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20630 IsEnclosedByDataEnvironmentExpr =
true;
20635 std::prev(CI)->getAssociatedDeclaration()->getType();
20637 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20656 if (CI == CE || SI == SE) {
20659 diag::err_omp_pointer_mapped_along_with_derived_section)
20665 if (CI->getAssociatedExpression()->getStmtClass() !=
20666 SI->getAssociatedExpression()->getStmtClass() ||
20667 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20668 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20669 assert(CI != CE && SI != SE);
20670 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20683 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20684 if (CKind == OMPC_map) {
20685 if (CI != CE || SI != SE) {
20689 CI != CE ? CurComponents.begin() : StackComponents.begin();
20690 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20692 while (It != End && !It->getAssociatedDeclaration())
20693 std::advance(It, 1);
20694 assert(It != End &&
20695 "Expected at least one component with the declaration.");
20696 if (It !=
Begin && It->getAssociatedDeclaration()
20698 .getCanonicalType()
20699 ->isAnyPointerType()) {
20700 IsEnclosedByDataEnvironmentExpr =
false;
20701 EnclosingExpr =
nullptr;
20705 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20707 assert(CKind == OMPC_to || CKind == OMPC_from);
20708 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20718 if (!CurrentRegionOnly && SI != SE)
20719 EnclosingExpr = RE;
20723 IsEnclosedByDataEnvironmentExpr |=
20724 (!CurrentRegionOnly && CI != CE && SI == SE);
20729 if (CurrentRegionOnly)
20743 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20745 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20761 Expr *UnresolvedMapper) {
20777 while (S && !S->isDeclScope(
D))
20778 S = S->getParent();
20780 S = S->getParent();
20781 Lookups.emplace_back();
20782 Lookups.back().append(Lookup.
begin(), Lookup.
end());
20785 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20789 auto *DMD = cast<OMPDeclareMapperDecl>(
D);
20790 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
20791 Lookups.back().addDecl(DMD);
20799 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
20800 return !D->isInvalidDecl() &&
20801 (D->getType()->isDependentType() ||
20802 D->getType()->isInstantiationDependentType() ||
20803 D->getType()->containsUnexpandedParameterPack());
20814 false, URS.
begin(), URS.
end(),
false,
20822 SemaRef.
Diag(
Loc, diag::err_omp_mapper_wrong_type);
20829 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20839 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20843 !
Type.isMoreQualifiedThan(
D->getType()))
20862 SemaRef.
Diag(
Loc, diag::err_omp_invalid_mapper)
20872struct MappableVarListInfo {
20887 VarComponents.reserve(VarList.size());
20888 VarBaseDeclarations.reserve(VarList.size());
20907 for (
auto *FD : RD->
fields()) {
20915 SExprs.push_back(BE);
20923 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
20926 Maps.push_back(MapClause);
20927 return MapperVarRef;
20931 DSAStackTy *Stack) {
20946 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
20948 BaseType, MapperId, Maps,
nullptr);
20954 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
20958 DMD->setMapperVarRef(MapperVarRef);
20978 while (S && !S->isDeclScope(
D))
20979 S = S->getParent();
20981 S = S->getParent();
20982 Lookups.emplace_back();
20983 Lookups.back().append(Lookup.
begin(), Lookup.
end());
20989 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
20990 return !D->isInvalidDecl() &&
20991 (D->getType()->isDependentType() ||
20992 D->getType()->isInstantiationDependentType() ||
20993 D->getType()->containsUnexpandedParameterPack());
21000 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21010 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21014 !
Type.isMoreQualifiedThan(
D->getType()))
21023 bool IsAmbiguous = !Paths.isAmbiguous(
21039 {CanonType,
nullptr});
21040 llvm::DenseMap<const Type *, bool>
Visited;
21042 while (!Types.empty()) {
21043 auto [BaseType, CurFD] = Types.pop_back_val();
21044 while (ParentChain.back().second == 0)
21045 ParentChain.pop_back();
21046 --ParentChain.back().second;
21047 if (BaseType.isNull())
21050 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21053 auto It =
Visited.find(BaseType.getTypePtr());
21063 DefaultMapperId, BaseType);
21064 It =
Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21070 bool FirstIter =
true;
21080 ParentChain.emplace_back(CurFD, 1);
21082 ++ParentChain.back().second;
21084 Types.emplace_back(FieldTy, FD);
21103 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
21105 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21106 "Unexpected clause kind with mappable expressions!");
21114 MapperId.
setName(DeclNames.getIdentifier(
21116 MapperId.
setLoc(StartLoc);
21120 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21121 bool UpdateUMIt =
false;
21122 Expr *UnresolvedMapper =
nullptr;
21124 bool HasHoldModifier =
21125 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21133 for (
Expr *RE : MVLI.VarList) {
21134 assert(RE &&
"Null expr in omp to/from/map clause");
21138 if (UpdateUMIt && UMIt != UMEnd) {
21142 "Expect the size of UnresolvedMappers to match with that of VarList");
21146 UnresolvedMapper = *UMIt;
21155 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
21159 MVLI.UDMapperList.push_back(ER.
get());
21162 MVLI.ProcessedVarList.push_back(RE);
21171 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21174 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21187 DSAS->getCurrentDirective(), NoDiagnose);
21191 assert(!CurComponents.empty() &&
21192 "Invalid mappable expression information.");
21194 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21196 DSAS->addMappedClassesQualTypes(TE->getType());
21199 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
21203 MVLI.UDMapperList.push_back(ER.
get());
21205 MVLI.ProcessedVarList.push_back(RE);
21206 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21207 MVLI.VarComponents.back().append(CurComponents.begin(),
21208 CurComponents.end());
21209 MVLI.VarBaseDeclarations.push_back(
nullptr);
21216 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21217 assert(CurDeclaration &&
"Null decl on map clause.");
21220 "Expecting components to have associated only canonical declarations.");
21222 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21223 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21225 assert((VD || FD) &&
"Only variables or fields are expected here!");
21232 if (VD && DSAS->isThreadPrivate(VD)) {
21235 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21236 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21237 << getOpenMPClauseName(CKind);
21251 true, CurComponents, CKind))
21253 if (CKind == OMPC_map &&
21256 false, CurComponents, CKind))
21263 auto I = llvm::find_if(
21268 assert(I != CurComponents.end() &&
"Null decl on map clause.");
21271 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->
IgnoreParens());
21272 auto *OASE = dyn_cast<ArraySectionExpr>(VE->
IgnoreParens());
21273 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->
IgnoreParens());
21275 Type = ASE->getType().getNonReferenceType();
21280 Type = ATy->getElementType();
21283 Type =
Type.getNonReferenceType();
21284 }
else if (OAShE) {
21298 if (CKind == OMPC_map) {
21305 if (DKind == OMPD_target_enter_data &&
21306 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21308 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21309 << (IsMapTypeImplicit ? 1 : 0)
21311 << getOpenMPDirectiveName(DKind);
21320 if (DKind == OMPD_target_exit_data &&
21321 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21322 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
21323 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21324 << (IsMapTypeImplicit ? 1 : 0)
21326 << getOpenMPDirectiveName(DKind);
21335 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21337 SemaRef.
Diag(StartLoc,
21338 diag::err_omp_invalid_map_type_modifier_for_directive)
21340 OMPC_MAP_MODIFIER_ompx_hold)
21341 << getOpenMPDirectiveName(DKind);
21349 if ((DKind == OMPD_target_data ||
21351 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21352 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21353 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21354 << (IsMapTypeImplicit ? 1 : 0)
21356 << getOpenMPDirectiveName(DKind);
21368 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
21370 DKind == OMPD_target)) {
21371 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21373 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21374 << getOpenMPClauseName(DVar.CKind)
21375 << getOpenMPClauseName(OMPC_map)
21376 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21385 SemaRef, DSAS->
getCurScope(), MapperIdScopeSpec, MapperId,
21386 Type.getCanonicalType(), UnresolvedMapper);
21389 if (!ER.
get() && isa<ArraySectionExpr>(VE)) {
21397 ElemType = ATy->getElementType();
21407 MVLI.UDMapperList.push_back(ER.
get());
21410 MVLI.ProcessedVarList.push_back(RE);
21414 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21420 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21421 MVLI.VarComponents.back().append(CurComponents.begin(),
21422 CurComponents.end());
21423 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ?
nullptr
21443 BuiltinType::OMPIterator))
21445 diag::err_omp_map_modifier_not_iterator);
21448 unsigned Count = 0;
21449 for (
unsigned I = 0,
E = MapTypeModifiers.size(); I <
E; ++I) {
21451 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21452 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21456 "Modifiers exceed the allowed number of map type modifiers");
21457 Modifiers[Count] = MapTypeModifiers[I];
21458 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21462 MappableVarListInfo MVLI(VarList);
21464 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21465 MapType, Modifiers, IsMapTypeImplicit,
21471 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21472 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21474 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21482 if (ReductionType.
isNull())
21490 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21495 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21499 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21503 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21506 return ReductionType;
21512 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21515 Decls.reserve(ReductionTypes.size());
21524 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21526 bool InCompoundScope =
true;
21527 if (S !=
nullptr) {
21536 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21538 while (Filter.hasNext()) {
21539 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21540 if (InCompoundScope) {
21541 auto I = UsedAsPrevious.find(PrevDecl);
21542 if (I == UsedAsPrevious.end())
21543 UsedAsPrevious[PrevDecl] =
false;
21545 UsedAsPrevious[
D] =
true;
21547 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21548 PrevDecl->getLocation();
21551 if (InCompoundScope) {
21552 for (
const auto &PrevData : UsedAsPrevious) {
21553 if (!PrevData.second) {
21554 PrevDRD = PrevData.first;
21559 }
else if (PrevDeclInScope !=
nullptr) {
21560 auto *PrevDRDInScope = PrevDRD =
21561 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21563 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21564 PrevDRDInScope->getLocation();
21565 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21566 }
while (PrevDRDInScope !=
nullptr);
21568 for (
const auto &TyData : ReductionTypes) {
21569 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21571 if (I != PreviousRedeclTypes.end()) {
21572 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21574 Diag(I->second, diag::note_previous_definition);
21577 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21579 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21581 DRD->setAccess(AS);
21582 Decls.push_back(DRD);
21584 DRD->setInvalidDecl();
21594 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21609 QualType ReductionType = DRD->getType();
21626 if (S !=
nullptr) {
21630 DRD->addDecl(OmpInParm);
21631 DRD->addDecl(OmpOutParm);
21637 DRD->setCombinerData(InE, OutE);
21642 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21649 if (Combiner !=
nullptr)
21650 DRD->setCombiner(Combiner);
21652 DRD->setInvalidDecl();
21657 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21671 QualType ReductionType = DRD->getType();
21688 if (S !=
nullptr) {
21692 DRD->addDecl(OmpPrivParm);
21693 DRD->addDecl(OmpOrigParm);
21699 DRD->setInitializerData(OrigE, PrivE);
21700 return OmpPrivParm;
21705 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21714 }
else if (OmpPrivParm->
hasInit()) {
21715 DRD->setInitializer(OmpPrivParm->
getInit(),
21720 DRD->setInvalidDecl();
21726 for (
Decl *
D : DeclReductions.
get()) {
21735 return DeclReductions;
21742 if (
D.isInvalidType())
21755 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
21758 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
21763 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21780 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21782 bool InCompoundScope =
true;
21783 if (S !=
nullptr) {
21792 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21794 while (Filter.hasNext()) {
21795 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21796 if (InCompoundScope) {
21797 auto I = UsedAsPrevious.find(PrevDecl);
21798 if (I == UsedAsPrevious.end())
21799 UsedAsPrevious[PrevDecl] =
false;
21801 UsedAsPrevious[
D] =
true;
21803 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21804 PrevDecl->getLocation();
21807 if (InCompoundScope) {
21808 for (
const auto &PrevData : UsedAsPrevious) {
21809 if (!PrevData.second) {
21810 PrevDMD = PrevData.first;
21815 }
else if (PrevDeclInScope) {
21816 auto *PrevDMDInScope = PrevDMD =
21817 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
21819 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
21820 PrevDMDInScope->getLocation();
21821 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
21822 }
while (PrevDMDInScope !=
nullptr);
21826 if (I != PreviousRedeclTypes.end()) {
21827 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
21828 << MapperType << Name;
21829 Diag(I->second, diag::note_previous_definition);
21837 ClausesWithImplicit);
21839 MapperType, VN, ClausesWithImplicit,
21845 DMD->setAccess(AS);
21847 DMD->setInvalidDecl();
21849 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21853 DMD->setMapperVarRef(MapperVarRef);
21874 if (
DSAStack->getDeclareMapperVarRef())
21879 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
21881 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
21894 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
21895 return cast<DeclRefExpr>(
DSAStack->getDeclareMapperVarRef())->getDecl();
21902 if (VarList.empty())
21905 for (
Expr *ValExpr : VarList) {
21918 LParenLoc, EndLoc, VarList,
21921 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21923 for (
Expr *ValExpr : VarList) {
21925 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
21926 Vars.push_back(ValExpr);
21931 LParenLoc, EndLoc, Vars, PreInit);
21938 if (VarList.empty())
21941 for (
Expr *ValExpr : VarList) {
21954 StartLoc, LParenLoc, EndLoc, VarList,
21957 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21959 for (
Expr *ValExpr : VarList) {
21961 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
21962 Vars.push_back(ValExpr);
21967 LParenLoc, EndLoc, Vars, PreInit);
21975 Stmt *HelperValStmt =
nullptr;
21981 ValExpr,
SemaRef, OMPC_priority,
21983 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
21987 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21995 "Unexpected grainsize modifier in OpenMP < 51.");
22000 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22001 << Values << getOpenMPClauseName(OMPC_grainsize);
22005 Expr *ValExpr = Grainsize;
22006 Stmt *HelperValStmt =
nullptr;
22016 &CaptureRegion, &HelperValStmt))
22021 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22029 "Unexpected num_tasks modifier in OpenMP < 51.");
22034 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22035 << Values << getOpenMPClauseName(OMPC_num_tasks);
22039 Expr *ValExpr = NumTasks;
22040 Stmt *HelperValStmt =
nullptr;
22047 ValExpr,
SemaRef, OMPC_num_tasks,
22049 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22054 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22074 DSAStackTy *Stack) {
22075 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22076 if (!OMPEventHandleT.
isNull())
22081 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
22084 Stack->setOMPEventHandleT(PT.
get());
22105 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
22115 <<
"omp_event_handle_t" << 1 << VD->
getType()
22122 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
22123 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22126 << getOpenMPClauseName(DVar.CKind)
22127 << getOpenMPClauseName(OMPC_firstprivate);
22142 std::string Values;
22146 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22147 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22150 Expr *ValExpr = ChunkSize;
22151 Stmt *HelperValStmt =
nullptr;
22162 ValExpr = Val.
get();
22167 if (std::optional<llvm::APSInt>
Result =
22169 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
22170 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22175 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22179 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22180 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22188 Kind, ValExpr, HelperValStmt);
22196 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22197 Kind != OMPC_DEFAULTMAP_scalar) {
22201 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22203 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22207 OMPC_DEFAULTMAP_scalar);
22211 Diag(
Loc, diag::err_omp_unexpected_clause_value)
22212 <<
Value << getOpenMPClauseName(OMPC_defaultmap);
22219 if (!isDefaultmapKind || !isDefaultmapModifier) {
22221 ?
"'scalar', 'aggregate', 'pointer'"
22222 :
"'scalar', 'aggregate', 'pointer', 'all'";
22224 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
22225 "'firstprivate', 'none', 'default'";
22226 if (!isDefaultmapKind && isDefaultmapModifier) {
22227 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22228 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22229 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22230 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22231 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22233 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22234 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22235 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22236 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22239 StringRef ModifierValue =
22240 "'alloc', 'from', 'to', 'tofrom', "
22241 "'firstprivate', 'none', 'default', 'present'";
22242 if (!isDefaultmapKind && isDefaultmapModifier) {
22243 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22244 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22245 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22246 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22247 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22249 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22250 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22251 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22252 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22261 if (
DSAStack->checkDefaultmapCategory(Kind)) {
22262 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22268 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22269 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22270 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22272 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22285 !isa<CXXRecordDecl>(CurLexicalContext) &&
22286 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22287 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22288 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22289 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
22295 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
22297 DeclareTargetNesting.push_back(DTCI);
22303 assert(!DeclareTargetNesting.empty() &&
22304 "check isInOpenMPDeclareTargetContext() first!");
22305 return DeclareTargetNesting.pop_back_val();
22315 if (DeclareTargetNesting.empty())
22318 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
22319 << getOpenMPDirectiveName(DTCI.
Kind);
22334 VarOrFuncDeclFilterCCC CCC(
SemaRef);
22345 Diag(
Id.getLoc(), diag::err_undeclared_var_use) <<
Id.getName();
22350 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22351 !isa<FunctionTemplateDecl>(ND)) {
22352 Diag(
Id.getLoc(), diag::err_omp_invalid_target_decl) <<
Id.getName();
22361 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22362 isa<FunctionTemplateDecl>(ND)) &&
22363 "Expected variable, function or function template.");
22365 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
22367 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22368 !VD->isStaticDataMember()) {
22369 Diag(
Loc, diag::err_omp_declare_target_has_local_vars)
22378 Diag(
Loc, diag::warn_omp_declare_target_after_first_use);
22382 Diag(
Loc, diag::warn_hip_omp_target_directives);
22385 const unsigned Level = -1;
22387 auto *VD = cast<ValueDecl>(ND);
22388 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22389 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22390 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
22391 (*ActiveAttr)->getLevel() == Level) {
22392 Diag(
Loc, diag::err_omp_device_type_mismatch)
22393 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
22394 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22395 (*ActiveAttr)->getDevType());
22398 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22399 (*ActiveAttr)->getLevel() == Level) {
22400 Diag(
Loc, diag::err_omp_declare_target_to_and_link) << ND;
22404 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22407 Expr *IndirectE =
nullptr;
22408 bool IsIndirect =
false;
22414 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22419 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22421 if (
auto *VD = dyn_cast<VarDecl>(ND);
22423 VD->hasGlobalStorage())
22429 if (!
D || !isa<VarDecl>(
D))
22431 auto *VD = cast<VarDecl>(
D);
22432 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
22433 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22434 if (SemaRef.
LangOpts.OpenMP >= 50 &&
22437 VD->hasGlobalStorage()) {
22438 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22439 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22446 diag::err_omp_lambda_capture_in_declare_target_not_to);
22447 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
22454 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
22455 SemaRef.
Diag(SL, diag::note_used_here) << SR;
22459 Sema &SemaRef, DSAStackTy *Stack,
22461 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22472 if (
auto *VD = dyn_cast<VarDecl>(
D)) {
22474 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22475 !VD->isStaticDataMember())
22479 if (
DSAStack->isThreadPrivate(VD)) {
22480 Diag(SL, diag::err_omp_threadprivate_in_target);
22485 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(
D))
22486 D = FTD->getTemplatedDecl();
22487 if (
auto *FD = dyn_cast<FunctionDecl>(
D)) {
22488 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22489 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22490 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22491 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22496 if (
auto *VD = dyn_cast<ValueDecl>(
D)) {
22504 if (isa<VarDecl>(
D) || isa<FunctionDecl>(
D) ||
22505 isa<FunctionTemplateDecl>(
D)) {
22506 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22507 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22508 unsigned Level = DeclareTargetNesting.size();
22509 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22512 Expr *IndirectE =
nullptr;
22513 bool IsIndirect =
false;
22519 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22521 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22522 : OMPDeclareTargetDeclAttr::MT_To,
22523 DTCI.
DT, IndirectE, IsIndirect, Level,
22527 ML->DeclarationMarkedOpenMPDeclareTarget(
D, A);
22547 if (
auto *VD = dyn_cast<VarDecl>(
Node->getDecl())) {
22549 DeclVector.push_back(VD);
22554 for (
auto *Child : Ex->
children()) {
22563 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
22564 DeclVector.push_back(cast<VarDecl>(TD));
22565 while (!DeclVector.empty()) {
22566 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22567 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
22581 if (isa<VarDecl>(TargetDecl))
22596 unsigned Count = 0;
22597 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22599 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22600 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22604 "Modifiers exceed the allowed number of motion modifiers");
22605 Modifiers[Count] = MotionModifiers[I];
22606 ModifiersLoc[Count] = MotionModifiersLoc[I];
22610 MappableVarListInfo MVLI(VarList);
22612 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22613 if (MVLI.ProcessedVarList.empty())
22617 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22618 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22633 unsigned Count = 0;
22634 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22636 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22637 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22641 "Modifiers exceed the allowed number of motion modifiers");
22642 Modifiers[Count] = MotionModifiers[I];
22643 ModifiersLoc[Count] = MotionModifiersLoc[I];
22647 MappableVarListInfo MVLI(VarList);
22649 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22650 if (MVLI.ProcessedVarList.empty())
22654 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22655 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22662 MappableVarListInfo MVLI(VarList);
22666 for (
Expr *RefExpr : VarList) {
22667 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
22670 Expr *SimpleRefExpr = RefExpr;
22674 MVLI.ProcessedVarList.push_back(RefExpr);
22675 PrivateCopies.push_back(
nullptr);
22676 Inits.push_back(
nullptr);
22683 Type =
Type.getNonReferenceType().getUnqualifiedType();
22685 auto *VD = dyn_cast<VarDecl>(
D);
22689 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22690 << 0 << RefExpr->getSourceRange();
22698 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
22699 if (VDPrivate->isInvalidDecl())
22704 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22720 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22721 PrivateCopies.push_back(VDPrivateRefExpr);
22722 Inits.push_back(VDInitRefExpr);
22727 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22731 MVLI.VarBaseDeclarations.push_back(
D);
22732 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22733 MVLI.VarComponents.back().emplace_back(SimpleRefExpr,
D,
22737 if (MVLI.ProcessedVarList.empty())
22741 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22742 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22748 MappableVarListInfo MVLI(VarList);
22750 for (
Expr *RefExpr : VarList) {
22751 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
22754 Expr *SimpleRefExpr = RefExpr;
22759 MVLI.ProcessedVarList.push_back(RefExpr);
22764 auto *VD = dyn_cast<VarDecl>(
D);
22771 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22776 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22780 MVLI.VarBaseDeclarations.push_back(
D);
22781 MVLI.VarComponents.emplace_back();
22782 Expr *Component = SimpleRefExpr;
22783 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22784 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22787 MVLI.VarComponents.back().emplace_back(Component,
D,
22791 if (MVLI.ProcessedVarList.empty())
22795 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22796 MVLI.VarComponents);
22802 MappableVarListInfo MVLI(VarList);
22803 for (
Expr *RefExpr : VarList) {
22804 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
22807 Expr *SimpleRefExpr = RefExpr;
22811 MVLI.ProcessedVarList.push_back(RefExpr);
22821 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22822 << 0 << RefExpr->getSourceRange();
22828 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
22830 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22831 << getOpenMPClauseName(DVar.CKind)
22832 << getOpenMPClauseName(OMPC_is_device_ptr)
22833 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
22838 const Expr *ConflictExpr;
22839 if (
DSAStack->checkMappableExprComponentListsForDecl(
22844 ConflictExpr = R.front().getAssociatedExpression();
22847 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22856 SimpleRefExpr,
D,
false);
22857 DSAStack->addMappableExpressionComponents(
22858 D, MC, OMPC_is_device_ptr);
22861 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
22866 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22867 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22868 "Unexpected device pointer expression!");
22869 MVLI.VarBaseDeclarations.push_back(
22870 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
22871 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22872 MVLI.VarComponents.back().push_back(MC);
22875 if (MVLI.ProcessedVarList.empty())
22879 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22880 MVLI.VarComponents);
22886 MappableVarListInfo MVLI(VarList);
22887 for (
Expr *RefExpr : VarList) {
22888 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
22891 Expr *SimpleRefExpr = RefExpr;
22896 MVLI.ProcessedVarList.push_back(RefExpr);
22904 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
22906 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22907 << getOpenMPClauseName(DVar.CKind)
22908 << getOpenMPClauseName(OMPC_has_device_addr)
22909 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
22914 const Expr *ConflictExpr;
22915 if (
DSAStack->checkMappableExprComponentListsForDecl(
22920 ConflictExpr = R.front().getAssociatedExpression();
22923 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22931 Expr *Component = SimpleRefExpr;
22932 auto *VD = dyn_cast<VarDecl>(
D);
22933 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22934 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22938 Component,
D,
false);
22939 DSAStack->addMappableExpressionComponents(
22940 D, MC, OMPC_has_device_addr);
22946 assert(Ref &&
"has_device_addr capture failed");
22947 MVLI.ProcessedVarList.push_back(Ref);
22949 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
22954 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22955 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22956 "Unexpected device pointer expression!");
22957 MVLI.VarBaseDeclarations.push_back(
22958 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
22959 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22960 MVLI.VarComponents.back().push_back(MC);
22963 if (MVLI.ProcessedVarList.empty())
22967 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22968 MVLI.VarComponents);
22984 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
22989 Allocator = AllocatorRes.
get();
23002 for (
Expr *RefExpr : VarList) {
23003 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
23006 Expr *SimpleRefExpr = RefExpr;
23010 Vars.push_back(RefExpr);
23016 auto *VD = dyn_cast<VarDecl>(
D);
23021 ? RefExpr->IgnoreParens()
23029 DSAStack->addInnerAllocatorExpr(Allocator);
23031 Allocator, ColonLoc, EndLoc, Vars);
23039 for (
Expr *RefExpr : VarList) {
23040 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23043 Expr *SimpleRefExpr = RefExpr;
23047 Vars.push_back(RefExpr);
23054 if (
const Expr *PrevRef =
23055 DSAStack->addUniqueNontemporal(
D, SimpleRefExpr)) {
23056 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23057 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23058 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23059 << getOpenMPClauseName(OMPC_nontemporal);
23063 Vars.push_back(RefExpr);
23091 for (
Expr *RefExpr : VarList) {
23092 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23095 Expr *SimpleRefExpr = RefExpr;
23100 Vars.push_back(RefExpr);
23105 const DSAStackTy::DSAVarData DVar =
23111 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23112 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23113 << RefExpr->getSourceRange();
23115 if (
DSAStack->getParentDirective() != OMPD_unknown)
23116 DSAStack->markDeclAsUsedInScanDirective(
D);
23117 Vars.push_back(RefExpr);
23132 for (
Expr *RefExpr : VarList) {
23133 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23136 Expr *SimpleRefExpr = RefExpr;
23141 Vars.push_back(RefExpr);
23147 DSAStackTy::DSAVarData DVar;
23148 if (ParentDirective != OMPD_unknown)
23154 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23155 DVar.Modifier != OMPC_REDUCTION_inscan) {
23156 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23157 << RefExpr->getSourceRange();
23159 DSAStack->markDeclAsUsedInScanDirective(
D);
23161 Vars.push_back(RefExpr);
23173 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23174 if (!OMPAlloctraitT.
isNull())
23179 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
23182 Stack->setOMPAlloctraitT(PT.
get());
23202 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23203 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
23204 StringRef Allocator =
23205 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23213 Expr *AllocatorExpr =
nullptr;
23215 if (
D.Allocator->isTypeDependent()) {
23216 AllocatorExpr =
D.Allocator;
23220 AllocatorExpr =
D.Allocator->IgnoreParenImpCasts();
23221 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23222 bool IsPredefinedAllocator =
false;
23224 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23226 IsPredefinedAllocator =
23228 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23232 bool IsTypeCompatible = IsPredefinedAllocator;
23233 IsTypeCompatible = IsTypeCompatible ||
23235 OMPAllocatorHandleT);
23237 IsTypeCompatible ||
23239 bool IsNonConstantLValue =
23241 if (!DRE || !IsTypeCompatible ||
23242 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23243 Diag(
D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23244 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
23251 if (IsPredefinedAllocator &&
D.AllocatorTraits) {
23252 Diag(
D.AllocatorTraits->getExprLoc(),
23253 diag::err_omp_predefined_allocator_with_traits)
23255 Diag(
D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23256 << cast<NamedDecl>(DRE->
getDecl())->getName()
23263 if (!IsPredefinedAllocator && !
D.AllocatorTraits) {
23264 Diag(
D.Allocator->getExprLoc(),
23265 diag::err_omp_nonpredefined_allocator_without_traits);
23269 if (!
D.AllocatorTraits)
23273 IsPredefinedAllocator
23274 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23275 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23277 Expr *AllocatorTraitsExpr =
nullptr;
23278 if (
D.AllocatorTraits) {
23279 if (
D.AllocatorTraits->isTypeDependent()) {
23280 AllocatorTraitsExpr =
D.AllocatorTraits;
23286 AllocatorTraitsExpr =
D.AllocatorTraits->IgnoreParenImpCasts();
23291 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23292 TraitTy = ConstArrayTy->getElementType();
23298 Diag(
D.AllocatorTraits->getExprLoc(),
23299 diag::err_omp_expected_array_alloctraits)
23300 << AllocatorTraitsExpr->
getType();
23305 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23308 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23325 for (
Expr *RefExpr : Locators) {
23326 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
23327 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23329 Vars.push_back(RefExpr);
23337 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23338 << 1 << 0 << RefExpr->getSourceRange();
23347 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23348 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23349 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23350 << 1 << 0 << RefExpr->getSourceRange();
23353 Vars.push_back(SimpleExpr);
23357 ColonLoc, EndLoc, Modifier, Vars);
23366 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23369 << getOpenMPClauseName(OMPC_bind);
23374 LParenLoc, EndLoc);
23381 Expr *ValExpr = Size;
23382 Stmt *HelperValStmt =
nullptr;
23393 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
23394 if (CaptureRegion != OMPD_unknown &&
23397 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23398 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23403 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23411 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
23412 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23413 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23414 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23415 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23416 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23422 llvm::APSInt TotalDepCount(32);
23425 DepType == OMPC_DOACROSS_source ||
23426 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23427 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23429 Vars = VarOffset.Vars;
23430 OpsOffs = VarOffset.OpsOffs;
23431 TotalDepCount = VarOffset.TotalDepCount;
23433 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23434 TotalDepCount.getZExtValue());
23435 if (
DSAStack->isParentOrderedRegion())
23436 DSAStack->addDoacrossDependClause(
C, OpsOffs);
23465 case OMPC_contains:
23468 llvm_unreachable(
"Unexpected OpenMP clause");
23476 case OMPC_no_openmp:
23478 case OMPC_no_openmp_routines:
23480 case OMPC_no_parallelism:
23483 llvm_unreachable(
"Unexpected OpenMP clause");
23492 if (
Base->hasPlaceholderType() &&
23493 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23506 LowerBound =
Result.get();
23508 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23528 if (
Base->isTypeDependent() ||
23531 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23535 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23547 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23548 <<
Base->getSourceRange());
23554 if (Res.isInvalid())
23556 diag::err_omp_typecheck_section_not_integer)
23558 LowerBound = Res.get();
23568 if (Res.isInvalid())
23570 diag::err_omp_typecheck_section_not_integer)
23571 << 1 << Length->getSourceRange());
23572 Length = Res.get();
23574 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23575 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23576 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23577 << 1 << Length->getSourceRange();
23584 diag::err_omp_typecheck_section_not_integer)
23586 Stride = Res.
get();
23599 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
23600 << ResultTy <<
Base->getSourceRange();
23605 diag::err_omp_section_incomplete_type,
Base))
23613 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
23614 if (LowerBoundValue.isNegative()) {
23616 diag::err_omp_section_not_subset_of_array)
23625 if (Length->EvaluateAsInt(
Result, Context)) {
23628 llvm::APSInt LengthValue =
Result.Val.getInt();
23629 if (LengthValue.isNegative()) {
23630 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23631 <<
toString(LengthValue, 10,
true)
23632 << Length->getSourceRange();
23636 }
else if (ColonLocFirst.
isValid() &&
23642 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23652 llvm::APSInt StrideValue =
Result.Val.getInt();
23653 if (!StrideValue.isStrictlyPositive()) {
23654 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
23655 <<
toString(StrideValue, 10,
true)
23662 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23670 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23677 if (
Base->hasPlaceholderType()) {
23691 LParenLoc, RParenLoc, Dims, Brackets);
23693 (!
Base->isTypeDependent() &&
23696 diag::err_omp_non_pointer_type_array_shaping_base)
23697 <<
Base->getSourceRange());
23700 bool ErrorFound =
false;
23701 for (
Expr *Dim : Dims) {
23702 if (Dim->hasPlaceholderType()) {
23704 if (
Result.isInvalid()) {
23709 if (
Result.isInvalid()) {
23715 if (!Dim->isTypeDependent()) {
23718 if (
Result.isInvalid()) {
23720 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23721 << Dim->getSourceRange();
23726 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23731 if (!
Value.isStrictlyPositive()) {
23732 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23734 << Dim->getSourceRange();
23740 NewDims.push_back(Dim);
23745 LParenLoc, RParenLoc, NewDims, Brackets);
23755 bool IsCorrect =
true;
23760 if (!
D.Type.getAsOpaquePtr()) {
23764 DeclTy = Context.
IntTy;
23765 StartLoc =
D.DeclIdentLoc;
23771 bool IsDeclTyDependent = DeclTy->isDependentType() ||
23772 DeclTy->containsUnexpandedParameterPack() ||
23773 DeclTy->isInstantiationDependentType();
23774 if (!IsDeclTyDependent) {
23775 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23778 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23783 if (DeclTy.isConstant(Context)) {
23786 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23794 assert(
D.DeclIdent &&
"Identifier expected.");
23799 D.DeclIdent, DeclTy, TInfo,
SC_None);
23805 RedeclarationKind::ForVisibleRedeclaration);
23827 if (!IsDeclTyDependent &&
Begin && !
Begin->isTypeDependent()) {
23832 Expr *End =
D.Range.End;
23833 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
23836 End = EndRes.
get();
23838 Expr *Step =
D.Range.Step;
23841 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
23846 std::optional<llvm::APSInt>
Result =
23852 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
23858 if (!
Begin || !End || !IsCorrect) {
23874 if (
Decl *ID =
D.IteratorDecl)
23875 ID->setInvalidDecl();
23887 D.Range.End,
D.Range.Begin);
23893 if (
D.Range.Step) {
23904 D.AssignmentLoc, BO_Sub, Res.
get(),
23921 D.AssignmentLoc, BO_Sub,
D.Range.Begin,
D.Range.End);
23935 D.AssignmentLoc, BO_Sub, Res1.
get(),
23950 D.AssignmentLoc, BO_GT,
D.Range.Step,
23975 CounterVD->setImplicit();
23982 if (
D.Range.Step) {
23984 D.AssignmentLoc, BO_Mul,
23994 D.Range.Begin, UpdateRes.
get());
24001 cast<VarDecl>(
D.IteratorDecl)->getType(),
24004 VDRes.
get(), UpdateRes.
get());
24016 D.AssignmentLoc, UO_PreInc, RefRes.
get());
24017 if (!CounterUpdateRes.
isUsable()) {
24023 if (!CounterUpdateRes.
isUsable()) {
24034 Helpers.assign(ID.size(), {});
24039 if (
Decl *ID =
D.IteratorDecl)
24040 ID->setInvalidDecl();
24045 LLoc, RLoc, ID, Helpers);
24050 StringRef AssumptionStr) {
24051 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24054 unsigned BestEditDistance = 3;
24055 StringRef Suggestion;
24056 for (
const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24057 unsigned EditDistance =
24058 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24059 if (EditDistance < BestEditDistance) {
24060 Suggestion = KnownAssumptionIt.getKey();
24061 BestEditDistance = EditDistance;
24065 if (!Suggestion.empty())
24066 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24067 << AssumptionStr << Suggestion;
24069 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown)
24086 :
SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
enum clang::sema::@1658::IndirectLocalPathEntry::EntryKind Kind
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
llvm::DenseSet< const void * > Visited
static const Decl * getCanonicalDecl(const Decl *D)
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::TargetList TargetList
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, StringRef DiagType="")
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude=std::nullopt)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static 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 checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
static QualType getPointeeType(const MemRegion *R)
Allows QualTypes to be sorted and hence used in maps and sets.
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
ASTContext & getParentASTContext() const
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
A reference to a declared variable, function, enum, etc.
SourceLocation getBeginLoc() const LLVM_READONLY
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
SourceLocation getEndLoc() const LLVM_READONLY
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getEndLoc() const
const DeclGroupRef getDeclGroup() const
const Decl * getSingleDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
bool isReferenced() const
Whether any declaration of this entity was referenced.
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
bool isInvalidDecl() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
void setAccess(AccessSpecifier AS)
SourceLocation getLocation() const
void setImplicit(bool I=true)
void setReferenced(bool R=true)
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
SourceLocation getBeginLoc() const LLVM_READONLY
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
void setLexicalDeclContext(DeclContext *DC)
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
RAII object that enters a new expression evaluation context.
The return type of classify().
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
ArrayRef< ParmVarDecl * > parameters() const
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Represents a prototype with parameter type info, e.g.
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A class for iterating through a result set and possibly filtering out results.
Represents the results of name lookup.
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
DeclClass * getAsSingle() const
bool empty() const
Return true if no decls were found.
Filter makeFilter()
Create a filter for this result set.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
A C++ nested-name-specifier augmented with source location information.
static OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the '#pragma omp ...' directive.
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
This represents 'at' clause in the '#pragma omp error' directive.
SourceLocation getAtKindKwLoc() const
Returns location of clause kind.
OpenMPAtClauseKind getAtKind() const
Returns kind of the clause.
This represents 'atomic_default_mem_order' clause in the '#pragma omp requires' directive.
static OMPAtomicDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expressions Exprs)
Creates directive with a list of Clauses and 'x', 'v' and 'expr' parts of the atomic construct (see S...
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
This represents 'bind' clause in the '#pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCanonicalLoop * create(const ASTContext &Ctx, Stmt *LoopStmt, CapturedStmt *DistanceFunc, CapturedStmt *LoopVarFunc, DeclRefExpr *LoopVarRef)
Create a new OMPCanonicalLoop.
This represents 'capture' clause in the '#pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Class that represents a component of a mappable expression.
ValueDecl * getAssociatedDeclaration() const
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like '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 OMPContainsClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents '#pragma omp critical' directive.
static OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
This represents '#pragma omp declare mapper ...' directive.
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents '#pragma omp declare reduction ...' directive.
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the '#pragma omp ...' directive.
This represents 'defaultmap' clause in the '#pragma omp ...' directive.
This represents implicit clause 'depend' for the '#pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
static OMPDepobjDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
This represents 'destroy' clause in the '#pragma omp depobj' directive or the '#pragma omp interop' d...
This represents 'detach' clause in the '#pragma omp task' directive.
This represents 'device' clause in the '#pragma omp ...' directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
This represents 'dist_schedule' clause in the '#pragma omp ...' directive.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents the 'doacross' clause for the '#pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dynamic_allocators' clause in the '#pragma omp requires' directive.
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This is a basic class for representing single OpenMP executable directive.
OpenMPDirectiveKind getDirectiveKind() const
This represents 'fail' clause in the '#pragma omp atomic' directive.
This represents 'filter' clause in the '#pragma omp ...' directive.
This represents 'final' clause in the '#pragma omp ...' directive.
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFlushDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Representation of the 'full' clause of the '#pragma omp unroll' directive.
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the '#pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the '#pragma omp ...' directive.
This represents the 'holds' clause in the '#pragma omp assume' directive.
This represents 'if' clause in the '#pragma omp ...' directive.
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the '#pragma omp ...' directives.
Expr * getStep()
Returns linear step.
void setUpdates(ArrayRef< Expr * > UL)
Sets the list of update expressions for linear variables.
privates_range privates()
void setFinals(ArrayRef< Expr * > FL)
Sets the list of final update expressions for linear variables.
void setUsedExprs(ArrayRef< Expr * > UE)
Sets the list of used expressions for the linear clause.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
Expr * getCalcStep()
Returns expression to calculate linear step.
OpenMPLinearClauseKind getModifier() const
Return modifier.
The base class for all loop-based directives, including loop transformation directives.
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt)
Creates directive.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'mergeable' clause in the '#pragma omp ...' directive.
This represents 'message' clause in the '#pragma omp error' directive.
Expr * getMessageString() const
Returns message string of the clause.
This represents the 'no_openmp' clause in the '#pragma omp assume' directive.
This represents the 'no_openmp_routines' clause in the '#pragma omp assume' directive.
This represents the 'no_parallelism' clause in the '#pragma omp assume' directive.
This represents 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the '#pragma omp ...' directive.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
This represents 'order' clause in the '#pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the '#pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
static OMPOrderedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This represents 'priority' clause in the '#pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents 'read' clause in the '#pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
This represents '#pragma omp requires...' directive.
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp reverse'.
This represents 'reverse_offload' clause in the '#pragma omp requires' directive.
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
This represents 'schedule' clause in the '#pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
static OMPScopeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
static OMPSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
This represents 'seq_cst' clause in the '#pragma omp atomic' directive.
This represents 'severity' clause in the '#pragma omp error' directive.
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPTaskgroupDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *ReductionRef)
Creates directive.
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents '#pragma omp threadprivate ...' directive.
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threads' clause in the '#pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp tile'.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the '#pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the '#pragma omp requires' directive.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp unroll'.
This represents 'untied' clause in the '#pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
This represents the 'use' clause in '#pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
SourceLocation getLParenLoc() const
Returns the location of '('.
unsigned varlist_size() const
This represents 'weak' clause in the '#pragma omp atomic' directives.
This represents 'write' clause in the '#pragma omp atomic' directive.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the '#pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the '#pragma omp target ...' directive.
Wrapper for void* pointer.
void * getAsOpaquePtr() const
static OpaquePtr make(PtrTy P)
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
ParsedAttr - Represents a syntactic attribute.
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool hasQualifiers() const
Determine whether this type has any qualifiers.
QualType withRestrict() const
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType withConst() const
void addConst()
Add the const type qualifier to this QualType.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
bool isConstant(const ASTContext &Ctx) const
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
const Type * getTypePtrOrNull() const
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
const Scope * getParent() const
getParent - Return the scope that this is nested in.
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
A generic diagnostic builder for errors which may or may not be deferred.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'reduction' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the '#pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'from' clause.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'to' clause.
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
OMPClause * ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interchange' after parsing of its clauses and the associated state...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'task_reduction' clause.
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
std::pair< StringRef, QualType > CapturedParamNameType
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp tile' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Abstract base class used for diagnosing integer constant expression violations.
Sema - This implements semantic analysis and AST building for C.
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false) const
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
@ LookupAnyName
Look up any declaration with any name.
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
PoppedFunctionScopePtr PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP=nullptr, const Decl *D=nullptr, QualType BlockType=QualType())
Pop a function (or block or lambda or captured region) scope from the stack.
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit=false, bool BuildAndDiagnose=true, const unsigned *const FunctionScopeIndexToStopAt=nullptr, bool ByCopy=false)
Make sure the value of 'this' is actually available in the current context, if it is a potentially ev...
NamedDecl * HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists)
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
FPOptionsOverride CurFPFeatureOverrides()
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt=std::nullopt)
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
void CleanupVarDeclMarking()
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
ASTContext & getASTContext() const
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt)
Try to capture the given variable.
void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var)
Mark a variable referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
void PopExpressionEvaluationContext()
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef< Expr * > Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses)
Find the associated classes and namespaces for argument-dependent lookup for a call with the given se...
void PushFunctionScope()
Enter a new function scope.
const LangOptions & getLangOpts() const
TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, CorrectTypoKind Mode, DeclContext *MemberContext=nullptr, bool EnteringContext=false, const ObjCObjectPointerType *OPT=nullptr, bool RecordFailure=true)
Try to "correct" a typo in the source code by finding visible declarations whose names are similar to...
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)
Checks access for a hierarchy conversion.
void CheckExtraCXXDefaultArguments(Declarator &D)
CheckExtraCXXDefaultArguments - Check for any extra default arguments in the declarator,...
const LangOptions & LangOpts
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
DeclContext * getCurLexicalContext() const
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
sema::FunctionScopeInfo * getCurFunction() const
Expr * BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit)
Build a CXXThisExpr and mark it referenced in the current context.
ExprResult DefaultLvalueConversion(Expr *E)
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
@ TryCapture_ExplicitByVal
bool areMultiversionVariantFunctionsCompatible(const FunctionDecl *OldFD, const FunctionDecl *NewFD, const PartialDiagnostic &NoProtoDiagID, const PartialDiagnosticAt &NoteCausedDiagIDAt, const PartialDiagnosticAt &NoSupportDiagIDAt, const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported, bool ConstexprSupported, bool CLinkageMayDiffer)
Checks if the variant/multiversion functions are compatible.
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
void setFunctionHasBranchProtectedScope()
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
TypeSourceInfo * GetTypeForDeclarator(Declarator &D)
GetTypeForDeclarator - Convert the type for the specified declarator to Type instances.
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace)
Filters out lookup results that don't fall within the given scope as determined by isDeclInScope.
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
sema::FunctionScopeInfo * getEnclosingFunction() const
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
FullExprArg MakeFullExpr(Expr *Arg)
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool isTLSSupported() const
Whether the target supports thread-local storage.
bool isVLASupported() const
Whether target supports variable-length arrays.
Represents a declaration of a type.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
bool isArithmeticType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isScalarType() const
bool isVariableArrayType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAnyComplexType() const
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isFunctionProtoType() const
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
bool isFunctionType() const
bool isStructureOrClassType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool isFunctionNoProtoType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
void setType(QualType newType)
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
void setInitStyle(InitializationStyle Style)
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
@ CallInit
Call-style initialization (C++98)
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Directive - Abstract class representing a parsed verify directive.
Retains information about a captured region.
unsigned short OpenMPLevel
unsigned short OpenMPCaptureLevel
Retains information about a function, method, or block that is currently being parsed.
void setHasOMPDeclareReductionCombiner()
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Defines the clang::TargetInfo interface.
bool LE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Expr * AssertSuccess(ExprResult R)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ LCK_This
Capturing the *this object by reference.
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
OpenMPGrainsizeClauseModifier
OpenMPNumTasksClauseModifier
ActionResult< Expr * > ExprResult
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ActionResult< Decl * > DeclResult
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
bool isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a combined construct for which the first construct is a parallel...
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Extra information about a function prototype.
llvm::SmallVector< Expr *, 4 > PreferTypes
Iterator definition representation.
SourceLocation AssignmentLoc
SourceLocation SecondColonLoc
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Expr * Upper
Normalized upper bound.
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
VarDecl * CounterVD
Internal normalized counter.
Expr * ParForInDistCond
'omp parallel for' loop condition used when composed with 'omp distribute' in the same construct and ...
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Expr * LastIteration
Loop last iteration number.
Expr * Cond
Loop condition.
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Expr * IL
IsLastIteration - local flag variable passed to runtime.
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Expr * CalcLastIteration
Calculation of last iteration.
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Expr * ST
Stride - local variable passed to runtime.
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Expr * PreCond
Loop pre-condition.
Stmt * PreInits
Init statement for all captured expressions.
Expr * IterationVarRef
Loop iteration variable.
Expr * NumIterations
Loop number of iterations.
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
void clear(unsigned Size)
Initialize all the fields to null.
Expr * Inc
Loop increment.
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Expr * UB
UpperBound - local variable passed to runtime.
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Expr * LB
LowerBound - local variable passed to runtime.
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Expr * Init
Loop iteration variable init.
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
std::optional< Expr * > Indirect
The directive with indirect clause.
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
SourceLocation Loc
The directive location.
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Data structure for iterator expression.
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Clang specific specialization of the OMPContext to lookup target features.