43#include "llvm/ADT/IndexedMap.h"
44#include "llvm/ADT/PointerEmbeddedInt.h"
45#include "llvm/ADT/STLExtras.h"
46#include "llvm/ADT/Sequence.h"
47#include "llvm/ADT/SetVector.h"
48#include "llvm/ADT/SmallSet.h"
49#include "llvm/ADT/StringExtras.h"
50#include "llvm/Frontend/OpenMP/OMPAssume.h"
51#include "llvm/Frontend/OpenMP/OMPConstants.h"
52#include "llvm/Frontend/OpenMP/OMPVersion.h"
53#include "llvm/IR/Assumptions.h"
58using namespace llvm::omp;
73enum DefaultDataSharingAttributes {
78 DSA_firstprivate = 1 << 3,
85enum DefaultDataSharingVCAttributes {
99 unsigned Modifier = 0;
100 const Expr *RefExpr =
nullptr;
101 DeclRefExpr *PrivateCopy =
nullptr;
102 SourceLocation ImplicitDSALoc;
103 bool AppliedToPointee =
false;
104 DSAVarData() =
default;
106 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
107 SourceLocation ImplicitDSALoc,
unsigned Modifier,
108 bool AppliedToPointee)
109 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
110 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
111 AppliedToPointee(AppliedToPointee) {}
113 using OperatorOffsetTy =
114 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
115 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
117 enum class UsesAllocatorsDeclKind {
121 UserDefinedAllocator,
129 unsigned Modifier = 0;
132 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
133 DeclRefExpr *PrivateCopy =
nullptr;
136 bool AppliedToPointee =
false;
138 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
139 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
140 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
141 using LoopControlVariablesMapTy =
142 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
145 struct MappedExprComponentTy {
149 using MappedExprComponentsTy =
150 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
151 using CriticalsWithHintsTy =
152 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
153 struct ReductionData {
154 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
155 SourceRange ReductionRange;
156 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
157 ReductionData() =
default;
162 void set(
const Expr *RefExpr, SourceRange RR) {
164 ReductionOp = RefExpr;
167 using DeclReductionMapTy =
168 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
169 struct DefaultmapInfo {
173 DefaultmapInfo() =
default;
175 : ImplicitBehavior(M), SLoc(Loc) {}
178 struct SharingMapTy {
179 DeclSAMapTy SharingMap;
180 DeclReductionMapTy ReductionMap;
181 UsedRefMapTy AlignedMap;
182 UsedRefMapTy NontemporalMap;
183 MappedExprComponentsTy MappedExprComponents;
184 LoopControlVariablesMapTy LCVMap;
187 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
188 SourceLocation DefaultAttrLoc;
189 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
190 SourceLocation DefaultAttrVCLoc;
193 DeclarationNameInfo DirectiveName;
194 Scope *CurScope =
nullptr;
195 DeclContext *Context =
nullptr;
196 SourceLocation ConstructLoc;
200 DoacrossClauseMapTy DoacrossDepends;
204 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
205 bool RegionHasOrderConcurrent =
false;
206 unsigned AssociatedLoops = 1;
207 bool HasMutipleLoops =
false;
208 const Decl *PossiblyLoopCounter =
nullptr;
209 bool NowaitRegion =
false;
210 bool UntiedRegion =
false;
211 bool CancelRegion =
false;
212 bool LoopStart =
false;
213 bool BodyComplete =
false;
214 SourceLocation PrevScanLocation;
215 SourceLocation PrevOrderedLocation;
216 SourceLocation InnerTeamsRegionLoc;
218 Expr *TaskgroupReductionRef =
nullptr;
219 llvm::DenseSet<QualType> MappedClassesQualTypes;
220 SmallVector<Expr *, 4> InnerUsedAllocators;
221 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
224 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
226 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
227 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
231 struct ImplicitDefaultFDInfoTy {
233 const FieldDecl *FD =
nullptr;
235 size_t StackLevel = 0;
237 VarDecl *VD =
nullptr;
238 ImplicitDefaultFDInfoTy(
const FieldDecl *FD,
size_t StackLevel,
240 : FD(FD), StackLevel(StackLevel), VD(VD) {}
243 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
244 ImplicitDefaultFirstprivateFDs;
245 Expr *DeclareMapperVar =
nullptr;
246 SmallVector<VarDecl *, 16> IteratorVarDecls;
248 Scope *CurScope, SourceLocation Loc)
249 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
251 SharingMapTy() =
default;
254 using StackTy = SmallVector<SharingMapTy, 4>;
257 DeclSAMapTy Threadprivates;
258 DeclSAMapTy Groupprivates;
259 const FunctionScopeInfo *CurrentNonCapturingFunctionScope =
nullptr;
260 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
265 bool ForceCapturing =
false;
268 bool ForceCaptureByReferenceInTargetExecutable =
false;
269 CriticalsWithHintsTy Criticals;
270 unsigned IgnoredStackElements = 0;
274 using const_iterator = StackTy::const_reverse_iterator;
275 const_iterator begin()
const {
276 return Stack.empty() ? const_iterator()
277 : Stack.back().first.rbegin() + IgnoredStackElements;
279 const_iterator end()
const {
280 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
282 using iterator = StackTy::reverse_iterator;
284 return Stack.empty() ? iterator()
285 : Stack.back().first.rbegin() + IgnoredStackElements;
288 return Stack.empty() ? iterator() : Stack.back().first.rend();
293 bool isStackEmpty()
const {
294 return Stack.empty() ||
295 Stack.back().second != CurrentNonCapturingFunctionScope ||
296 Stack.back().first.size() <= IgnoredStackElements;
298 size_t getStackSize()
const {
299 return isStackEmpty() ? 0
300 : Stack.back().first.size() - IgnoredStackElements;
303 SharingMapTy *getTopOfStackOrNull() {
304 size_t Size = getStackSize();
307 return &Stack.back().first[
Size - 1];
309 const SharingMapTy *getTopOfStackOrNull()
const {
310 return const_cast<DSAStackTy &
>(*this).getTopOfStackOrNull();
312 SharingMapTy &getTopOfStack() {
313 assert(!isStackEmpty() &&
"no current directive");
314 return *getTopOfStackOrNull();
316 const SharingMapTy &getTopOfStack()
const {
317 return const_cast<DSAStackTy &
>(*this).getTopOfStack();
320 SharingMapTy *getSecondOnStackOrNull() {
321 size_t Size = getStackSize();
324 return &Stack.back().first[
Size - 2];
326 const SharingMapTy *getSecondOnStackOrNull()
const {
327 return const_cast<DSAStackTy &
>(*this).getSecondOnStackOrNull();
336 SharingMapTy &getStackElemAtLevel(
unsigned Level) {
337 assert(
Level < getStackSize() &&
"no such stack element");
338 return Stack.back().first[
Level];
340 const SharingMapTy &getStackElemAtLevel(
unsigned Level)
const {
341 return const_cast<DSAStackTy &
>(*this).getStackElemAtLevel(
Level);
344 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D)
const;
347 bool isOpenMPLocal(VarDecl *D, const_iterator Iter)
const;
350 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
352 QualType OMPAllocatorHandleT;
356 QualType OMPEventHandleT;
358 QualType OMPAlloctraitT;
360 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
363 SmallVector<SourceLocation, 2> TargetLocations;
364 SourceLocation AtomicLocation;
366 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
369 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
372 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
374 QualType getOMPAllocatorHandleT()
const {
return OMPAllocatorHandleT; }
376 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
378 QualType getOMPAlloctraitT()
const {
return OMPAlloctraitT; }
380 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
382 OMPPredefinedAllocators[AllocatorKind] = Allocator;
385 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind)
const {
386 return OMPPredefinedAllocators[AllocatorKind];
389 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
391 QualType getOMPDependT()
const {
return OMPDependT; }
394 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
396 QualType getOMPEventHandleT()
const {
return OMPEventHandleT; }
398 bool isClauseParsingMode()
const {
return ClauseKindMode != OMPC_unknown; }
400 assert(isClauseParsingMode() &&
"Must be in clause parsing mode.");
401 return ClauseKindMode;
405 bool isBodyComplete()
const {
406 const SharingMapTy *Top = getTopOfStackOrNull();
407 return Top && Top->BodyComplete;
409 void setBodyComplete() { getTopOfStack().BodyComplete =
true; }
411 bool isForceVarCapturing()
const {
return ForceCapturing; }
412 void setForceVarCapturing(
bool V) { ForceCapturing =
V; }
414 void setForceCaptureByReferenceInTargetExecutable(
bool V) {
415 ForceCaptureByReferenceInTargetExecutable =
V;
417 bool isForceCaptureByReferenceInTargetExecutable()
const {
418 return ForceCaptureByReferenceInTargetExecutable;
422 Scope *CurScope, SourceLocation Loc) {
423 assert(!IgnoredStackElements &&
424 "cannot change stack while ignoring elements");
426 Stack.back().second != CurrentNonCapturingFunctionScope)
427 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
428 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
429 Stack.back().first.back().DefaultAttrLoc = Loc;
433 assert(!IgnoredStackElements &&
434 "cannot change stack while ignoring elements");
435 assert(!Stack.back().first.empty() &&
436 "Data-sharing attributes stack is empty!");
437 Stack.back().first.pop_back();
442 class ParentDirectiveScope {
447 ParentDirectiveScope(DSAStackTy &Self,
bool Activate)
448 : Self(Self), Active(
false) {
452 ~ParentDirectiveScope() { disable(); }
455 --Self.IgnoredStackElements;
461 ++Self.IgnoredStackElements;
470 "Expected loop-based directive.");
471 getTopOfStack().LoopStart =
true;
476 "Expected loop-based directive.");
477 getTopOfStack().LoopStart =
false;
480 bool isLoopStarted()
const {
482 "Expected loop-based directive.");
483 return !getTopOfStack().LoopStart;
486 void resetPossibleLoopCounter(
const Decl *D =
nullptr) {
487 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
490 const Decl *getPossiblyLoopCounter()
const {
491 return getTopOfStack().PossiblyLoopCounter;
494 void pushFunction() {
495 assert(!IgnoredStackElements &&
496 "cannot change stack while ignoring elements");
497 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
499 CurrentNonCapturingFunctionScope = CurFnScope;
502 void popFunction(
const FunctionScopeInfo *OldFSI) {
503 assert(!IgnoredStackElements &&
504 "cannot change stack while ignoring elements");
505 if (!Stack.empty() && Stack.back().second == OldFSI) {
506 assert(Stack.back().first.empty());
509 CurrentNonCapturingFunctionScope =
nullptr;
510 for (
const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
512 CurrentNonCapturingFunctionScope = FSI;
518 void addCriticalWithHint(
const OMPCriticalDirective *D, llvm::APSInt Hint) {
521 std::pair<const OMPCriticalDirective *, llvm::APSInt>
522 getCriticalWithHint(
const DeclarationNameInfo &Name)
const {
524 if (I != Criticals.end())
526 return std::make_pair(
nullptr, llvm::APSInt());
531 const Expr *addUniqueAligned(
const ValueDecl *D,
const Expr *NewDE);
535 const Expr *addUniqueNontemporal(
const ValueDecl *D,
const Expr *NewDE);
538 void addLoopControlVariable(
const ValueDecl *D, VarDecl *
Capture);
543 const LCDeclInfo isLoopControlVariable(
const ValueDecl *D)
const;
548 const LCDeclInfo isParentLoopControlVariable(
const ValueDecl *D)
const;
553 const LCDeclInfo isLoopControlVariable(
const ValueDecl *D,
554 unsigned Level)
const;
557 const ValueDecl *getParentLoopControlVariable(
unsigned I)
const;
560 void markDeclAsUsedInScanDirective(ValueDecl *D) {
561 if (SharingMapTy *Stack = getSecondOnStackOrNull())
562 Stack->UsedInScanDirective.insert(D);
566 bool isUsedInScanDirective(ValueDecl *D)
const {
567 if (
const SharingMapTy *Stack = getTopOfStackOrNull())
568 return Stack->UsedInScanDirective.contains(D);
574 DeclRefExpr *PrivateCopy =
nullptr,
unsigned Modifier = 0,
575 bool AppliedToPointee =
false);
579 void addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
583 void addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
584 const Expr *ReductionRef);
588 getTopMostTaskgroupReductionData(
const ValueDecl *D, SourceRange &SR,
590 Expr *&TaskgroupDescriptor)
const;
594 getTopMostTaskgroupReductionData(
const ValueDecl *D, SourceRange &SR,
595 const Expr *&ReductionRef,
596 Expr *&TaskgroupDescriptor)
const;
599 Expr *getTaskgroupReductionRef()
const {
600 assert((getTopOfStack().
Directive == OMPD_taskgroup ||
604 "taskgroup reference expression requested for non taskgroup or "
605 "parallel/worksharing directive.");
606 return getTopOfStack().TaskgroupReductionRef;
610 bool isTaskgroupReductionRef(
const ValueDecl *VD,
unsigned Level)
const {
611 return getStackElemAtLevel(
Level).TaskgroupReductionRef &&
618 const DSAVarData getTopDSA(ValueDecl *D,
bool FromParent);
620 const DSAVarData getImplicitDSA(ValueDecl *D,
bool FromParent)
const;
622 const DSAVarData getImplicitDSA(ValueDecl *D,
unsigned Level)
const;
629 DefaultDataSharingAttributes)>
632 bool FromParent)
const;
637 hasInnermostDSA(ValueDecl *D,
640 bool FromParent)
const;
645 hasExplicitDSA(
const ValueDecl *D,
647 unsigned Level,
bool NotLastprivate =
false)
const;
651 bool hasExplicitDirective(
653 unsigned Level)
const;
657 const llvm::function_ref<
bool(
660 bool FromParent)
const;
664 const SharingMapTy *Top = getTopOfStackOrNull();
665 return Top ? Top->Directive : OMPD_unknown;
669 assert(!isStackEmpty() &&
"No directive at specified level.");
670 return getStackElemAtLevel(
Level).Directive;
674 unsigned OpenMPCaptureLevel)
const {
675 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
677 return CaptureRegions[OpenMPCaptureLevel];
681 const SharingMapTy *Parent = getSecondOnStackOrNull();
682 return Parent ? Parent->Directive : OMPD_unknown;
686 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
688 ArrayRef<const OMPRequiresDecl *> getRequiresDecls()
const {
689 return RequiresDecls;
693 template <
typename ClauseType>
bool hasRequiresDeclWithClause()
const {
694 return llvm::any_of(RequiresDecls, [](
const OMPRequiresDecl *D) {
695 return llvm::any_of(D->
clauselists(), [](
const OMPClause *
C) {
696 return isa<ClauseType>(C);
703 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList)
const {
704 bool IsDuplicate =
false;
705 for (OMPClause *CNew : ClauseList) {
706 for (
const OMPRequiresDecl *D : RequiresDecls) {
707 for (
const OMPClause *CPrev : D->clauselists()) {
708 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
709 SemaRef.Diag(CNew->getBeginLoc(),
710 diag::err_omp_requires_clause_redeclaration)
712 SemaRef.Diag(CPrev->getBeginLoc(),
713 diag::note_omp_requires_previous_clause)
724 void addTargetDirLocation(SourceLocation LocStart) {
725 TargetLocations.push_back(LocStart);
729 void addAtomicDirectiveLoc(SourceLocation Loc) {
730 if (AtomicLocation.isInvalid())
731 AtomicLocation = Loc;
736 SourceLocation getAtomicDirectiveLoc()
const {
return AtomicLocation; }
739 ArrayRef<SourceLocation> getEncounteredTargetLocs()
const {
740 return TargetLocations;
744 void setDefaultDSANone(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_none;
746 getTopOfStack().DefaultAttrLoc = Loc;
749 void setDefaultDSAShared(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_shared;
751 getTopOfStack().DefaultAttrLoc = Loc;
754 void setDefaultDSAPrivate(SourceLocation Loc) {
755 getTopOfStack().DefaultAttr = DSA_private;
756 getTopOfStack().DefaultAttrLoc = Loc;
759 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
760 getTopOfStack().DefaultAttr = DSA_firstprivate;
761 getTopOfStack().DefaultAttrLoc = Loc;
764 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
765 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
766 getTopOfStack().DefaultAttrVCLoc = VCLoc;
769 void setDefaultDSAVCAll(SourceLocation VCLoc) {
770 getTopOfStack().DefaultVCAttr = DSA_VC_all;
771 getTopOfStack().DefaultAttrVCLoc = VCLoc;
774 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
775 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
776 getTopOfStack().DefaultAttrVCLoc = VCLoc;
779 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
780 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
781 getTopOfStack().DefaultAttrVCLoc = VCLoc;
786 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[
Kind];
787 DMI.ImplicitBehavior = M;
793 return getTopOfStack()
794 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
797 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
800 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
802 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
806 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
807 return ConstructTraits;
809 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
812 ConstructTraits.append(Traits.begin(), Traits.end());
814 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
815 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
816 assert(Top == Trait &&
"Something left a trait on the stack!");
822 DefaultDataSharingAttributes getDefaultDSA(
unsigned Level)
const {
823 return getStackSize() <=
Level ? DSA_unspecified
824 : getStackElemAtLevel(
Level).DefaultAttr;
826 DefaultDataSharingAttributes getDefaultDSA()
const {
827 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
829 SourceLocation getDefaultDSALocation()
const {
830 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
834 return isStackEmpty()
836 : getTopOfStack().DefaultmapMap[
Kind].ImplicitBehavior;
839 getDefaultmapModifierAtLevel(
unsigned Level,
841 return getStackElemAtLevel(
Level).DefaultmapMap[
Kind].ImplicitBehavior;
843 bool isDefaultmapCapturedByRef(
unsigned Level,
846 getDefaultmapModifierAtLevel(
Level, Kind);
847 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
848 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
849 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
850 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
851 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
852 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
860 case OMPC_DEFAULTMAP_scalar:
861 case OMPC_DEFAULTMAP_pointer:
863 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
864 (M == OMPC_DEFAULTMAP_MODIFIER_default);
865 case OMPC_DEFAULTMAP_aggregate:
866 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
870 llvm_unreachable(
"Unexpected OpenMPDefaultmapClauseKind enum");
872 bool mustBeFirstprivateAtLevel(
unsigned Level,
875 getDefaultmapModifierAtLevel(
Level, Kind);
876 return mustBeFirstprivateBase(M, Kind);
880 return mustBeFirstprivateBase(M, Kind);
884 bool isThreadPrivate(VarDecl *D) {
885 const DSAVarData DVar = getTopDSA(D,
false);
890 void setOrderedRegion(
bool IsOrdered,
const Expr *Param,
891 OMPOrderedClause *Clause) {
893 getTopOfStack().OrderedRegion.emplace(Param, Clause);
895 getTopOfStack().OrderedRegion.reset();
899 bool isOrderedRegion()
const {
900 if (
const SharingMapTy *Top = getTopOfStackOrNull())
901 return Top->OrderedRegion.has_value();
905 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam()
const {
906 if (
const SharingMapTy *Top = getTopOfStackOrNull())
907 if (Top->OrderedRegion)
908 return *Top->OrderedRegion;
909 return std::make_pair(
nullptr,
nullptr);
913 bool isParentOrderedRegion()
const {
914 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
915 return Parent->OrderedRegion.has_value();
919 std::pair<const Expr *, OMPOrderedClause *>
920 getParentOrderedRegionParam()
const {
921 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
922 if (Parent->OrderedRegion)
923 return *Parent->OrderedRegion;
924 return std::make_pair(
nullptr,
nullptr);
927 void setRegionHasOrderConcurrent(
bool HasOrderConcurrent) {
928 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
932 bool isEnclosingOrderConcurrent()
const {
933 for (const_iterator I = begin() + std::min<size_t>(1, getStackSize()),
936 if (I->RegionHasOrderConcurrent)
945 bool isInSimdRegion()
const {
946 for (const_iterator I = begin() + std::min<size_t>(1, getStackSize()),
952 I->Directive != OMPD_ordered_blockassoc)
958 void setNowaitRegion(
bool IsNowait =
true) {
959 getTopOfStack().NowaitRegion = IsNowait;
963 bool isParentNowaitRegion()
const {
964 if (
const SharingMapTy *Parent = getSecondOnStackOrNull())
965 return Parent->NowaitRegion;
969 void setUntiedRegion(
bool IsUntied =
true) {
970 getTopOfStack().UntiedRegion = IsUntied;
973 bool isUntiedRegion()
const {
974 const SharingMapTy *Top = getTopOfStackOrNull();
975 return Top ? Top->UntiedRegion :
false;
978 void setParentCancelRegion(
bool Cancel =
true) {
979 if (SharingMapTy *Parent = getSecondOnStackOrNull())
980 Parent->CancelRegion |= Cancel;
983 bool isCancelRegion()
const {
984 const SharingMapTy *Top = getTopOfStackOrNull();
985 return Top ? Top->CancelRegion :
false;
989 void setParentHasScanDirective(SourceLocation Loc) {
990 if (SharingMapTy *Parent = getSecondOnStackOrNull())
991 Parent->PrevScanLocation = Loc;
994 bool doesParentHasScanDirective()
const {
995 const SharingMapTy *Top = getSecondOnStackOrNull();
996 return Top ? Top->PrevScanLocation.isValid() :
false;
999 SourceLocation getParentScanDirectiveLoc()
const {
1000 const SharingMapTy *Top = getSecondOnStackOrNull();
1001 return Top ? Top->PrevScanLocation : SourceLocation();
1004 void setParentHasOrderedDirective(SourceLocation Loc) {
1005 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1006 Parent->PrevOrderedLocation = Loc;
1009 bool doesParentHasOrderedDirective()
const {
1010 const SharingMapTy *Top = getSecondOnStackOrNull();
1011 return Top ? Top->PrevOrderedLocation.isValid() :
false;
1014 SourceLocation getParentOrderedDirectiveLoc()
const {
1015 const SharingMapTy *Top = getSecondOnStackOrNull();
1016 return Top ? Top->PrevOrderedLocation : SourceLocation();
1020 void setAssociatedLoops(
unsigned Val) {
1021 getTopOfStack().AssociatedLoops = Val;
1023 getTopOfStack().HasMutipleLoops =
true;
1026 unsigned getAssociatedLoops()
const {
1027 const SharingMapTy *Top = getTopOfStackOrNull();
1028 return Top ? Top->AssociatedLoops : 0;
1031 bool hasMutipleLoops()
const {
1032 const SharingMapTy *Top = getTopOfStackOrNull();
1033 return Top ? Top->HasMutipleLoops :
false;
1038 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1039 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1040 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1043 bool hasInnerTeamsRegion()
const {
1044 return getInnerTeamsRegionLoc().
isValid();
1047 SourceLocation getInnerTeamsRegionLoc()
const {
1048 const SharingMapTy *Top = getTopOfStackOrNull();
1049 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1052 Scope *getCurScope()
const {
1053 const SharingMapTy *Top = getTopOfStackOrNull();
1054 return Top ? Top->CurScope :
nullptr;
1056 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1057 SourceLocation getConstructLoc()
const {
1058 const SharingMapTy *Top = getTopOfStackOrNull();
1059 return Top ? Top->ConstructLoc : SourceLocation();
1064 bool checkMappableExprComponentListsForDecl(
1065 const ValueDecl *VD,
bool CurrentRegionOnly,
1066 const llvm::function_ref<
1078 if (CurrentRegionOnly)
1081 std::advance(SI, 1);
1083 for (; SI != SE; ++SI) {
1084 auto MI = SI->MappedExprComponents.find(VD);
1085 if (MI != SI->MappedExprComponents.end())
1087 MI->second.Components)
1088 if (Check(L, MI->second.Kind))
1096 bool checkMappableExprComponentListsForDeclAtLevel(
1097 const ValueDecl *VD,
unsigned Level,
1098 const llvm::function_ref<
1102 if (getStackSize() <=
Level)
1105 const SharingMapTy &StackElem = getStackElemAtLevel(
Level);
1106 auto MI = StackElem.MappedExprComponents.find(VD);
1107 if (MI != StackElem.MappedExprComponents.end())
1109 MI->second.Components)
1110 if (Check(L, MI->second.Kind))
1117 void addMappableExpressionComponents(
1118 const ValueDecl *VD,
1121 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1123 MEC.Components.resize(MEC.Components.size() + 1);
1124 MEC.Components.back().append(Components.begin(), Components.end());
1125 MEC.Kind = WhereFoundClauseKind;
1128 unsigned getNestingLevel()
const {
1129 assert(!isStackEmpty());
1130 return getStackSize() - 1;
1132 void addDoacrossDependClause(OMPClause *
C,
const OperatorOffsetTy &OpsOffs) {
1133 SharingMapTy *Parent = getSecondOnStackOrNull();
1135 Parent->DoacrossDepends.try_emplace(
C, OpsOffs);
1137 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1138 getDoacrossDependClauses()
const {
1139 const SharingMapTy &StackElem = getTopOfStack();
1141 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1142 return llvm::make_range(Ref.begin(), Ref.end());
1144 return llvm::make_range(StackElem.DoacrossDepends.end(),
1145 StackElem.DoacrossDepends.end());
1149 void addMappedClassesQualTypes(QualType QT) {
1150 SharingMapTy &StackElem = getTopOfStack();
1151 StackElem.MappedClassesQualTypes.insert(QT);
1155 bool isClassPreviouslyMapped(QualType QT)
const {
1156 const SharingMapTy &StackElem = getTopOfStack();
1157 return StackElem.MappedClassesQualTypes.contains(QT);
1161 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1162 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1163 E->
getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1164 "Expected declare target link global.");
1165 for (
auto &Elem : *
this) {
1167 Elem.DeclareTargetLinkVarDecls.push_back(E);
1175 ArrayRef<DeclRefExpr *> getLinkGlobals()
const {
1177 "Expected target executable directive.");
1178 return getTopOfStack().DeclareTargetLinkVarDecls;
1182 void addInnerAllocatorExpr(Expr *E) {
1183 getTopOfStack().InnerUsedAllocators.push_back(E);
1186 ArrayRef<Expr *> getInnerAllocators()
const {
1187 return getTopOfStack().InnerUsedAllocators;
1191 void addImplicitTaskFirstprivate(
unsigned Level, Decl *D) {
1192 getStackElemAtLevel(
Level).ImplicitTaskFirstprivates.insert(D);
1195 bool isImplicitTaskFirstprivate(Decl *D)
const {
1196 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1200 void addUsesAllocatorsDecl(
const Decl *D, UsesAllocatorsDeclKind Kind) {
1201 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1205 std::optional<UsesAllocatorsDeclKind>
1206 isUsesAllocatorsDecl(
unsigned Level,
const Decl *D)
const {
1207 const SharingMapTy &StackElem = getTopOfStack();
1208 auto I = StackElem.UsesAllocatorsDecls.find(D);
1209 if (I == StackElem.UsesAllocatorsDecls.end())
1210 return std::nullopt;
1211 return I->getSecond();
1213 std::optional<UsesAllocatorsDeclKind>
1214 isUsesAllocatorsDecl(
const Decl *D)
const {
1215 const SharingMapTy &StackElem = getTopOfStack();
1216 auto I = StackElem.UsesAllocatorsDecls.find(D);
1217 if (I == StackElem.UsesAllocatorsDecls.end())
1218 return std::nullopt;
1219 return I->getSecond();
1222 void addDeclareMapperVarRef(Expr *Ref) {
1223 SharingMapTy &StackElem = getTopOfStack();
1224 StackElem.DeclareMapperVar = Ref;
1226 const Expr *getDeclareMapperVarRef()
const {
1227 const SharingMapTy *Top = getTopOfStackOrNull();
1228 return Top ? Top->DeclareMapperVar :
nullptr;
1232 void addIteratorVarDecl(VarDecl *VD) {
1233 SharingMapTy &StackElem = getTopOfStack();
1237 bool isIteratorVarDecl(
const VarDecl *VD)
const {
1238 const SharingMapTy *Top = getTopOfStackOrNull();
1245 VarDecl *getImplicitFDCapExprDecl(
const FieldDecl *FD)
const {
1246 const_iterator I = begin();
1247 const_iterator EndI = end();
1248 size_t StackLevel = getStackSize();
1249 for (; I != EndI; ++I) {
1250 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1254 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1257 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1258 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1263 bool isImplicitDefaultFirstprivateFD(VarDecl *VD)
const {
1264 const_iterator I = begin();
1265 const_iterator EndI = end();
1266 for (; I != EndI; ++I)
1267 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1271 for (
const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1277 void addImplicitDefaultFirstprivateFD(
const FieldDecl *FD, VarDecl *VD) {
1278 iterator I = begin();
1279 const_iterator EndI = end();
1280 size_t StackLevel = getStackSize();
1281 for (; I != EndI; ++I) {
1282 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1283 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1288 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1290 void setOrderedToBlockAssociated() {
1291 assert(getCurrentDirective() == OMPD_ordered_standalone);
1292 getTopOfStack().Directive = OMPD_ordered_blockassoc;
1302 DKind == OMPD_unknown;
1308 if (
const auto *FE = dyn_cast<FullExpr>(E))
1309 E = FE->getSubExpr();
1311 if (
const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1312 E = MTE->getSubExpr();
1314 while (
const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1315 E = Binder->getSubExpr();
1317 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1318 E = ICE->getSubExprAsWritten();
1327 if (
const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1328 if (
const auto *ME = dyn_cast<MemberExpr>(
getExprAsWritten(CED->getInit())))
1329 D = ME->getMemberDecl();
1341 if (
C == OMPC_threadprivate)
1342 return getOpenMPClauseName(
C).str() +
" or thread local";
1343 return getOpenMPClauseName(
C).str();
1349 auto *VD = dyn_cast<VarDecl>(D);
1350 const auto *FD = dyn_cast<FieldDecl>(D);
1352 if (Iter == end()) {
1359 DVar.CKind = OMPC_shared;
1366 DVar.CKind = OMPC_shared;
1370 DVar.CKind = OMPC_shared;
1381 DVar.CKind = OMPC_private;
1385 DVar.DKind = Iter->Directive;
1388 if (Iter->SharingMap.count(D)) {
1389 const DSAInfo &
Data = Iter->SharingMap.lookup(D);
1390 DVar.RefExpr =
Data.RefExpr.getPointer();
1391 DVar.PrivateCopy =
Data.PrivateCopy;
1392 DVar.CKind =
Data.Attributes;
1393 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1394 DVar.Modifier =
Data.Modifier;
1395 DVar.AppliedToPointee =
Data.AppliedToPointee;
1403 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1404 switch (Iter->DefaultVCAttr) {
1405 case DSA_VC_aggregate:
1409 case DSA_VC_pointer:
1427 DVar.CKind = OMPC_shared;
1428 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1432 case DSA_firstprivate:
1435 DVar.CKind = OMPC_unknown;
1437 DVar.CKind = OMPC_firstprivate;
1439 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1447 DVar.CKind = OMPC_unknown;
1449 DVar.CKind = OMPC_private;
1451 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1453 case DSA_unspecified:
1458 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1462 DVar.CKind = OMPC_shared;
1472 DSAVarData DVarTemp;
1473 const_iterator I = Iter, E = end();
1481 DVarTemp = getDSA(I, D);
1482 if (DVarTemp.CKind != OMPC_shared) {
1483 DVar.RefExpr =
nullptr;
1484 DVar.CKind = OMPC_firstprivate;
1487 }
while (I != E && !isImplicitTaskingRegion(I->Directive));
1489 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1498 return getDSA(++Iter, D);
1501const Expr *DSAStackTy::addUniqueAligned(
const ValueDecl *D,
1502 const Expr *NewDE) {
1503 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1505 SharingMapTy &StackElem = getTopOfStack();
1506 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1508 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1511 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1515const Expr *DSAStackTy::addUniqueNontemporal(
const ValueDecl *D,
1516 const Expr *NewDE) {
1517 assert(!isStackEmpty() &&
"Data sharing attributes stack is empty");
1519 SharingMapTy &StackElem = getTopOfStack();
1520 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1522 assert(NewDE &&
"Unexpected nullptr expr to be added into aligned map");
1525 assert(It->second &&
"Unexpected nullptr expr in the aligned map");
1529void DSAStackTy::addLoopControlVariable(
const ValueDecl *D, VarDecl *
Capture) {
1530 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1532 SharingMapTy &StackElem = getTopOfStack();
1533 StackElem.LCVMap.try_emplace(
1534 D, LCDeclInfo(StackElem.LCVMap.size() + 1,
Capture));
1537const DSAStackTy::LCDeclInfo
1538DSAStackTy::isLoopControlVariable(
const ValueDecl *D)
const {
1539 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1541 const SharingMapTy &StackElem = getTopOfStack();
1542 auto It = StackElem.LCVMap.find(D);
1543 if (It != StackElem.LCVMap.end())
1545 return {0,
nullptr};
1548const DSAStackTy::LCDeclInfo
1549DSAStackTy::isLoopControlVariable(
const ValueDecl *D,
unsigned Level)
const {
1550 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1552 for (
unsigned I =
Level + 1; I > 0; --I) {
1553 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1554 auto It = StackElem.LCVMap.find(D);
1555 if (It != StackElem.LCVMap.end())
1558 return {0,
nullptr};
1561const DSAStackTy::LCDeclInfo
1562DSAStackTy::isParentLoopControlVariable(
const ValueDecl *D)
const {
1563 const SharingMapTy *Parent = getSecondOnStackOrNull();
1564 assert(Parent &&
"Data-sharing attributes stack is empty");
1566 auto It = Parent->LCVMap.find(D);
1567 if (It != Parent->LCVMap.end())
1569 return {0,
nullptr};
1572const ValueDecl *DSAStackTy::getParentLoopControlVariable(
unsigned I)
const {
1573 const SharingMapTy *Parent = getSecondOnStackOrNull();
1574 assert(Parent &&
"Data-sharing attributes stack is empty");
1575 if (Parent->LCVMap.size() < I)
1577 for (
const auto &Pair : Parent->LCVMap)
1578 if (Pair.second.first == I)
1583void DSAStackTy::addDSA(
const ValueDecl *D,
const Expr *E,
OpenMPClauseKind A,
1584 DeclRefExpr *PrivateCopy,
unsigned Modifier,
1585 bool AppliedToPointee) {
1587 if (A == OMPC_threadprivate) {
1588 DSAInfo &
Data = Threadprivates[D];
1589 Data.Attributes = A;
1590 Data.RefExpr.setPointer(E);
1591 Data.PrivateCopy =
nullptr;
1592 Data.Modifier = Modifier;
1593 }
else if (A == OMPC_groupprivate) {
1594 DSAInfo &
Data = Groupprivates[D];
1595 Data.Attributes = A;
1596 Data.RefExpr.setPointer(E);
1597 Data.PrivateCopy =
nullptr;
1598 Data.Modifier = Modifier;
1600 DSAInfo &
Data = getTopOfStack().SharingMap[D];
1601 assert(
Data.Attributes == OMPC_unknown || (A ==
Data.Attributes) ||
1602 (A == OMPC_firstprivate &&
Data.Attributes == OMPC_lastprivate) ||
1603 (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) ||
1604 (isLoopControlVariable(D).first && A == OMPC_private));
1605 Data.Modifier = Modifier;
1606 if (A == OMPC_lastprivate &&
Data.Attributes == OMPC_firstprivate) {
1607 Data.RefExpr.setInt(
true);
1610 const bool IsLastprivate =
1611 A == OMPC_lastprivate ||
Data.Attributes == OMPC_lastprivate;
1612 Data.Attributes = A;
1613 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1614 Data.PrivateCopy = PrivateCopy;
1615 Data.AppliedToPointee = AppliedToPointee;
1617 DSAInfo &
Data = getTopOfStack().SharingMap[PrivateCopy->
getDecl()];
1618 Data.Modifier = Modifier;
1619 Data.Attributes = A;
1620 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1621 Data.PrivateCopy =
nullptr;
1622 Data.AppliedToPointee = AppliedToPointee;
1629 StringRef Name,
const AttrVec *Attrs =
nullptr,
1644 OMPReferencedVarAttr::CreateImplicit(SemaRef.
Context, OrigRef));
1651 bool RefersToCapture =
false) {
1659void DSAStackTy::addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
1662 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1664 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1665 "Additional reduction info may be specified only for reduction items.");
1666 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1667 assert(ReductionData.ReductionRange.isInvalid() &&
1668 (getTopOfStack().
Directive == OMPD_taskgroup ||
1672 "Additional reduction info may be specified only once for reduction "
1674 ReductionData.set(BOK, SR);
1675 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1676 if (!TaskgroupReductionRef) {
1679 TaskgroupReductionRef =
1684void DSAStackTy::addTaskgroupReductionData(
const ValueDecl *D, SourceRange SR,
1685 const Expr *ReductionRef) {
1687 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty");
1689 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1690 "Additional reduction info may be specified only for reduction items.");
1691 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1692 assert(ReductionData.ReductionRange.isInvalid() &&
1693 (getTopOfStack().
Directive == OMPD_taskgroup ||
1697 "Additional reduction info may be specified only once for reduction "
1699 ReductionData.set(ReductionRef, SR);
1700 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1701 if (!TaskgroupReductionRef) {
1704 TaskgroupReductionRef =
1709const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1711 Expr *&TaskgroupDescriptor)
const {
1713 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1714 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1715 const DSAInfo &
Data = I->SharingMap.lookup(D);
1716 if (
Data.Attributes != OMPC_reduction ||
1717 Data.Modifier != OMPC_REDUCTION_task)
1719 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1720 if (!ReductionData.ReductionOp ||
1722 return DSAVarData();
1723 SR = ReductionData.ReductionRange;
1725 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1726 "expression for the descriptor is not "
1728 TaskgroupDescriptor = I->TaskgroupReductionRef;
1729 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1730 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1733 return DSAVarData();
1736const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1737 const ValueDecl *D, SourceRange &SR,
const Expr *&ReductionRef,
1738 Expr *&TaskgroupDescriptor)
const {
1740 assert(!isStackEmpty() &&
"Data-sharing attributes stack is empty.");
1741 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1742 const DSAInfo &
Data = I->SharingMap.lookup(D);
1743 if (
Data.Attributes != OMPC_reduction ||
1744 Data.Modifier != OMPC_REDUCTION_task)
1746 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1747 if (!ReductionData.ReductionOp ||
1749 return DSAVarData();
1750 SR = ReductionData.ReductionRange;
1752 assert(I->TaskgroupReductionRef &&
"taskgroup reduction reference "
1753 "expression for the descriptor is not "
1755 TaskgroupDescriptor = I->TaskgroupReductionRef;
1756 return DSAVarData(I->Directive, OMPC_reduction,
Data.RefExpr.getPointer(),
1757 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1760 return DSAVarData();
1763bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I)
const {
1765 for (const_iterator E = end(); I != E; ++I) {
1766 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1769 Scope *TopScope = I->CurScope->getParent();
1770 Scope *CurScope = getCurScope();
1771 while (CurScope && CurScope != TopScope && !CurScope->
isDeclScope(D))
1773 return CurScope != TopScope;
1776 if (I->Context == DC)
1785 bool AcceptIfMutable =
true,
1786 bool *IsClassType =
nullptr) {
1788 Type =
Type.getNonReferenceType().getCanonicalType();
1789 bool IsConstant =
Type.isConstant(Context);
1790 Type = Context.getBaseElementType(
Type);
1794 if (
const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1796 RD = CTD->getTemplatedDecl();
1806 bool AcceptIfMutable =
true,
1807 bool ListItemNotVar =
false) {
1811 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1812 : IsClassType ? diag::err_omp_const_not_mutable_variable
1813 : diag::err_omp_const_variable;
1815 if (!ListItemNotVar && D) {
1816 const VarDecl *VD = dyn_cast<VarDecl>(D);
1820 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1828const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1833 auto *VD = dyn_cast<VarDecl>(D);
1834 auto TI = Threadprivates.find(D);
1835 if (TI != Threadprivates.end()) {
1836 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1837 DVar.CKind = OMPC_threadprivate;
1838 DVar.Modifier = TI->getSecond().Modifier;
1841 if (VD && VD->
hasAttr<OMPThreadPrivateDeclAttr>()) {
1844 VD->
getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1845 DVar.CKind = OMPC_threadprivate;
1846 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1853 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
1860 DVar.CKind = OMPC_threadprivate;
1861 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1866 !isLoopControlVariable(D).first) {
1867 const_iterator IterTarget =
1868 std::find_if(begin(), end(), [](
const SharingMapTy &
Data) {
1871 if (IterTarget != end()) {
1872 const_iterator ParentIterTarget = IterTarget + 1;
1873 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1874 if (isOpenMPLocal(VD, Iter)) {
1878 DVar.CKind = OMPC_threadprivate;
1882 if (!isClauseParsingMode() || IterTarget != begin()) {
1883 auto DSAIter = IterTarget->SharingMap.find(D);
1884 if (DSAIter != IterTarget->SharingMap.end() &&
1886 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1887 DVar.CKind = OMPC_threadprivate;
1890 const_iterator End = end();
1892 D, std::distance(ParentIterTarget, End),
1896 IterTarget->ConstructLoc);
1897 DVar.CKind = OMPC_threadprivate;
1917 const_iterator I = begin();
1918 const_iterator EndI = end();
1919 if (FromParent && I != EndI)
1922 auto It = I->SharingMap.find(D);
1923 if (It != I->SharingMap.end()) {
1924 const DSAInfo &
Data = It->getSecond();
1925 DVar.RefExpr =
Data.RefExpr.getPointer();
1926 DVar.PrivateCopy =
Data.PrivateCopy;
1927 DVar.CKind =
Data.Attributes;
1928 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1929 DVar.DKind = I->Directive;
1930 DVar.Modifier =
Data.Modifier;
1931 DVar.AppliedToPointee =
Data.AppliedToPointee;
1936 DVar.CKind = OMPC_shared;
1943 if (SemaRef.
LangOpts.OpenMP <= 31) {
1951 DSAVarData DVarTemp = hasInnermostDSA(
1954 return C == OMPC_firstprivate ||
C == OMPC_shared;
1956 MatchesAlways, FromParent);
1957 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1960 DVar.CKind = OMPC_shared;
1967 const_iterator I = begin();
1968 const_iterator EndI = end();
1969 if (FromParent && I != EndI)
1973 auto It = I->SharingMap.find(D);
1974 if (It != I->SharingMap.end()) {
1975 const DSAInfo &
Data = It->getSecond();
1976 DVar.RefExpr =
Data.RefExpr.getPointer();
1977 DVar.PrivateCopy =
Data.PrivateCopy;
1978 DVar.CKind =
Data.Attributes;
1979 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1980 DVar.DKind = I->Directive;
1981 DVar.Modifier =
Data.Modifier;
1982 DVar.AppliedToPointee =
Data.AppliedToPointee;
1988const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1989 bool FromParent)
const {
1990 if (isStackEmpty()) {
1992 return getDSA(I, D);
1995 const_iterator StartI = begin();
1996 const_iterator EndI = end();
1997 if (FromParent && StartI != EndI)
1999 return getDSA(StartI, D);
2002const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
2003 unsigned Level)
const {
2004 if (getStackSize() <=
Level)
2005 return DSAVarData();
2007 const_iterator StartI = std::next(begin(), getStackSize() - 1 -
Level);
2008 return getDSA(StartI, D);
2011const DSAStackTy::DSAVarData
2012DSAStackTy::hasDSA(ValueDecl *D,
2014 DefaultDataSharingAttributes)>
2017 bool FromParent)
const {
2021 const_iterator I = begin();
2022 const_iterator EndI = end();
2023 if (FromParent && I != EndI)
2025 for (; I != EndI; ++I) {
2026 if (!DPred(I->Directive) &&
2027 !isImplicitOrExplicitTaskingRegion(I->Directive))
2029 const_iterator NewI = I;
2030 DSAVarData DVar = getDSA(NewI, D);
2031 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
2037const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
2038 ValueDecl *D,
const llvm::function_ref<
bool(
OpenMPClauseKind,
bool)> CPred,
2040 bool FromParent)
const {
2044 const_iterator StartI = begin();
2045 const_iterator EndI = end();
2046 if (FromParent && StartI != EndI)
2048 if (StartI == EndI || !DPred(StartI->Directive))
2050 const_iterator NewI = StartI;
2051 DSAVarData DVar = getDSA(NewI, D);
2052 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2057bool DSAStackTy::hasExplicitDSA(
2060 unsigned Level,
bool NotLastprivate)
const {
2061 if (getStackSize() <=
Level)
2064 const SharingMapTy &StackElem = getStackElemAtLevel(
Level);
2065 auto I = StackElem.SharingMap.find(D);
2066 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2067 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2068 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2071 auto LI = StackElem.LCVMap.find(D);
2072 if (LI != StackElem.LCVMap.end())
2073 return CPred(OMPC_private,
false);
2077bool DSAStackTy::hasExplicitDirective(
2079 unsigned Level)
const {
2080 if (getStackSize() <=
Level)
2082 const SharingMapTy &StackElem = getStackElemAtLevel(
Level);
2083 return DPred(StackElem.Directive);
2086bool DSAStackTy::hasDirective(
2088 const DeclarationNameInfo &, SourceLocation)>
2090 bool FromParent)
const {
2092 size_t Skip = FromParent ? 2 : 1;
2093 for (const_iterator I = begin() + std::min(
Skip, getStackSize()), E = end();
2095 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2101void SemaOpenMP::InitDataSharingAttributesStack() {
2102 VarDataSharingAttributesStack =
new DSAStackTy(SemaRef);
2105#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2112 return DSAStack->getRequiresDecls();
2115void SemaOpenMP::pushOpenMPFunctionRegion() {
DSAStack->pushFunction(); }
2123 "Expected OpenMP device compilation.");
2129enum class FunctionEmissionStatus {
2136SemaBase::SemaDiagnosticBuilder
2140 "Expected OpenMP device compilation.");
2142 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2147 Kind = SemaDiagnosticBuilder::K_Immediate;
2158 ? SemaDiagnosticBuilder::K_Deferred
2159 : SemaDiagnosticBuilder::K_Immediate;
2163 Kind = SemaDiagnosticBuilder::K_Nop;
2166 llvm_unreachable(
"CUDADiscarded unexpected in OpenMP device compilation");
2178 "Expected OpenMP host compilation.");
2180 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2185 Kind = SemaDiagnosticBuilder::K_Immediate;
2188 Kind = SemaDiagnosticBuilder::K_Deferred;
2193 Kind = SemaDiagnosticBuilder::K_Nop;
2203 if (LO.OpenMP <= 45) {
2205 return OMPC_DEFAULTMAP_scalar;
2206 return OMPC_DEFAULTMAP_aggregate;
2209 return OMPC_DEFAULTMAP_pointer;
2211 return OMPC_DEFAULTMAP_scalar;
2212 return OMPC_DEFAULTMAP_aggregate;
2216 unsigned OpenMPCaptureLevel)
const {
2217 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2220 bool IsByRef =
true;
2225 if (
const auto *BD = dyn_cast<BindingDecl>(D))
2226 Ty = BD->getDecomposedDecl()->getType();
2228 bool IsVariableUsedInMapClause =
false;
2293 bool IsVariableAssociatedWithSection =
false;
2294 bool IsVariableItselfMapped =
false;
2296 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2298 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2299 &IsVariableItselfMapped,
2306 if (WhereFoundClauseKind != OMPC_map &&
2307 WhereFoundClauseKind != OMPC_has_device_addr)
2310 auto EI = MapExprComponents.rbegin();
2311 auto EE = MapExprComponents.rend();
2313 assert(EI != EE &&
"Invalid map expression!");
2316 EI->getAssociatedDeclaration() == D) {
2317 IsVariableUsedInMapClause =
true;
2323 if (MapExprComponents.size() == 1) {
2324 IsVariableItselfMapped =
true;
2332 auto Last = std::prev(EE);
2334 dyn_cast<UnaryOperator>(
Last->getAssociatedExpression());
2335 if ((UO && UO->getOpcode() == UO_Deref) ||
2340 IsVariableAssociatedWithSection =
true;
2351 if (IsVariableUsedInMapClause) {
2368 IsByRef = IsVariableItselfMapped ||
2374 IsByRef = (
DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2377 DSAStack->isDefaultmapCapturedByRef(
2382 return K == OMPC_reduction && !AppliedToPointee;
2390 ((IsVariableUsedInMapClause &&
2391 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2396 return K == OMPC_firstprivate ||
2397 (K == OMPC_reduction && AppliedToPointee);
2400 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2410 !((
DSAStack->getDefaultDSA(Level) == DSA_firstprivate ||
2411 DSAStack->getDefaultDSA(Level) == DSA_private) &&
2415 !
DSAStack->isLoopControlVariable(D, Level).first);
2432unsigned SemaOpenMP::getOpenMPNestingLevel()
const {
2433 assert(getLangOpts().OpenMP);
2434 return DSAStack->getNestingLevel();
2444 !
DSAStack->isClauseParsingMode()) ||
2457 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2460 DefaultDataSharingAttributes DefaultAttr) {
2462 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2466 if (DVarPrivate.CKind != OMPC_unknown)
2472 Expr *CaptureExpr,
bool WithInit,
2478 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2481 if (
auto *BD = dyn_cast<BindingDecl>(D)) {
2482 if (!BD->getHoldingVar())
2485 auto *VD = dyn_cast<VarDecl>(D);
2494 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2504 DSAStackTy::DSAVarData DVarTop =
2506 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2511 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2515 llvm::reverse(
SemaRef.FunctionScopes),
2516 CheckScopeInfo ? (
SemaRef.FunctionScopes.size() - (StopAt + 1))
2520 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2539 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2545 if (CheckScopeInfo) {
2546 bool OpenMPFound =
false;
2547 for (
unsigned I = StopAt + 1; I > 0; --I) {
2551 if (
auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2561 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2562 (!
DSAStack->isClauseParsingMode() ||
2563 DSAStack->getParentDirective() != OMPD_unknown)) {
2564 auto &&Info =
DSAStack->isLoopControlVariable(D);
2567 isImplicitOrExplicitTaskingRegion(
DSAStack->getCurrentDirective())) ||
2568 (VD &&
DSAStack->isForceVarCapturing()))
2569 return VD ? VD : Info.second;
2570 DSAStackTy::DSAVarData DVarTop =
2572 if (DVarTop.CKind != OMPC_unknown &&
isOpenMPPrivate(DVarTop.CKind) &&
2574 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2581 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2589 if (VD && !VD->
hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2590 ((
DSAStack->getDefaultDSA() != DSA_none &&
2591 DSAStack->getDefaultDSA() != DSA_private &&
2592 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2593 DVarTop.CKind == OMPC_shared))
2595 auto *FD = dyn_cast<FieldDecl>(D);
2596 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2597 !DVarPrivate.PrivateCopy) {
2598 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2601 DefaultDataSharingAttributes DefaultAttr) {
2603 (DefaultAttr == DSA_firstprivate ||
2604 DefaultAttr == DSA_private);
2608 if (DVarPrivate.CKind == OMPC_unknown)
2614 if (
SemaRef.getCurrentThisType().isNull())
2627 SemaRef.CurContext->getParent(),
false);
2631 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2634 if (DVarPrivate.CKind != OMPC_unknown ||
2635 (VD && (
DSAStack->getDefaultDSA() == DSA_none ||
2636 DSAStack->getDefaultDSA() == DSA_private ||
2637 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2643void SemaOpenMP::adjustOpenMPTargetScopeIndex(
unsigned &FunctionScopesIndex,
2644 unsigned Level)
const {
2645 FunctionScopesIndex -= getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
2649 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2655 assert(
getLangOpts().OpenMP &&
"OpenMP must be enabled.");
2657 DSAStack->resetPossibleLoopCounter();
2663 unsigned CapLevel)
const {
2664 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2665 if (
DSAStack->getCurrentDirective() != OMPD_unknown &&
2666 (!
DSAStack->isClauseParsingMode() ||
2667 DSAStack->getParentDirective() != OMPD_unknown)) {
2668 DSAStackTy::DSAVarData DVarPrivate =
DSAStack->hasDSA(
2671 DefaultDataSharingAttributes DefaultAttr) {
2673 DefaultAttr == DSA_private;
2679 !
DSAStack->isLoopControlVariable(D).first)
2680 return OMPC_private;
2683 bool IsTriviallyCopyable =
2694 (IsTriviallyCopyable ||
2700 return OMPC_firstprivate;
2701 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2702 if (DVar.CKind != OMPC_shared &&
2703 !
DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2704 DSAStack->addImplicitTaskFirstprivate(Level, D);
2705 return OMPC_firstprivate;
2712 DSAStack->resetPossibleLoopCounter(D);
2714 return OMPC_private;
2717 DSAStack->isLoopControlVariable(D).first) &&
2722 return OMPC_private;
2724 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2730 return OMPC_private;
2735 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2736 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2737 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2738 return OMPC_private;
2742 (
DSAStack->isClauseParsingMode() &&
2743 DSAStack->getClauseParsingMode() == OMPC_private) ||
2748 return K == OMPD_taskgroup ||
2749 ((isOpenMPParallelDirective(K) ||
2750 isOpenMPWorksharingDirective(K)) &&
2751 !isOpenMPSimdDirective(K));
2754 DSAStack->isTaskgroupReductionRef(D, Level)))
2761 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2764 for (
unsigned I =
DSAStack->getNestingLevel() + 1; I > Level; --I) {
2765 const unsigned NewLevel = I - 1;
2769 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2777 if (
DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2787 if (
DSAStack->mustBeFirstprivateAtLevel(
2789 OMPC = OMPC_firstprivate;
2793 if (OMPC != OMPC_unknown)
2795 OMPCaptureKindAttr::CreateImplicit(getASTContext(),
unsigned(OMPC)));
2799 unsigned CaptureLevel)
const {
2800 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2805 const auto *VD = dyn_cast<VarDecl>(D);
2809 Regions[CaptureLevel] != OMPD_task;
2813 unsigned CaptureLevel)
const {
2814 assert(
getLangOpts().OpenMP &&
"OpenMP is not allowed");
2817 if (
const auto *VD = dyn_cast<VarDecl>(D)) {
2821 DSAStackTy::DSAVarData TopDVar =
2823 unsigned NumLevels =
2828 return (NumLevels == CaptureLevel + 1 &&
2829 (TopDVar.CKind != OMPC_shared ||
2830 DSAStack->getDefaultDSA() == DSA_firstprivate));
2833 DSAStackTy::DSAVarData DVar =
DSAStack->getImplicitDSA(D, Level);
2834 if (DVar.CKind != OMPC_shared)
2836 }
while (Level > 0);
2842void SemaOpenMP::DestroyDataSharingAttributesStack() {
delete DSAStack; }
2846 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2851 "Not in OpenMP declare variant scope!");
2853 OMPDeclareVariantScopes.pop_back();
2859 assert(
getLangOpts().OpenMP &&
"Expected OpenMP compilation mode.");
2860 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2864 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2867 if (!
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2868 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2871 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2872 if (
getLangOpts().OpenMPIsTargetDevice && DevTy &&
2873 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2875 StringRef HostDevTy =
2877 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2878 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2879 diag::note_omp_marked_device_type_here)
2885 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2889 for (OMPDeclareVariantAttr *A :
2890 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2893 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2894 OMPDeclareTargetDeclAttr::getDeviceType(
2895 VariantFD->getMostRecentDecl());
2896 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2902 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2906 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2907 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2908 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2909 diag::note_omp_marked_device_type_here)
2917 DSAStack->push(DKind, DirName, CurScope, Loc);
2918 SemaRef.PushExpressionEvaluationContext(
2927 DSAStack->setClauseParsingMode(OMPC_unknown);
2928 SemaRef.CleanupVarDeclMarking();
2931static std::pair<ValueDecl *, bool>
2933 SourceRange &ERange,
bool AllowArraySection =
false,
2934 bool AllowAssumedSizeArray =
false, StringRef DiagType =
"");
2939 bool InscanFound =
false;
2946 if (
C->getClauseKind() != OMPC_reduction)
2949 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2951 InscanLoc = RC->getModifierLoc();
2954 if (RC->getModifier() == OMPC_REDUCTION_task) {
2964 S.
Diag(RC->getModifierLoc(),
2965 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2971 if (
C->getClauseKind() != OMPC_reduction)
2974 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2977 : RC->getModifierLoc(),
2978 diag::err_omp_inscan_reduction_expected);
2979 S.
Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2982 for (
Expr *Ref : RC->varlist()) {
2983 assert(Ref &&
"NULL expr in OpenMP reduction clause.");
2986 Expr *SimpleRefExpr = Ref;
2993 S.
Diag(Ref->getExprLoc(),
2994 diag::err_omp_reduction_not_inclusive_exclusive)
2995 << Ref->getSourceRange();
3003 ArrayRef<OMPClause *> Clauses);
3004static DeclRefExpr *
buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
3009 const DSAStackTy::DSAVarData &DVar,
3010 bool IsLoopIterVar =
false);
3019 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
3021 for (
Expr *DE : Clause->varlist()) {
3022 if (DE->isValueDependent() || DE->isTypeDependent()) {
3023 PrivateCopies.push_back(
nullptr);
3028 assert(
SemaRef.CurContext->isDependentContext() &&
3029 "uncaptured data member in a non-dependent context");
3030 PrivateCopies.push_back(
nullptr);
3034 auto *D = DRE->getDecl();
3035 if (
auto *BD = dyn_cast<BindingDecl>(D)) {
3037 const DSAStackTy::DSAVarData DVar =
3039 if (DVar.CKind != OMPC_lastprivate) {
3042 PrivateCopies.push_back(
nullptr);
3046 SemaRef, DE->getExprLoc(),
Type.getUnqualifiedType(), BD->getName(),
3047 BD->hasAttrs() ? &BD->getAttrs() :
nullptr, DRE);
3048 SemaRef.ActOnUninitializedDecl(VDPrivate);
3050 PrivateCopies.push_back(
nullptr);
3059 const DSAStackTy::DSAVarData DVar =
3061 if (DVar.CKind != OMPC_lastprivate) {
3064 PrivateCopies.push_back(
nullptr);
3075 SemaRef.ActOnUninitializedDecl(VDPrivate);
3077 PrivateCopies.push_back(
nullptr);
3083 Clause->setPrivateCopies(PrivateCopies);
3089 for (
Expr *RefExpr : Clause->varlist()) {
3090 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
3093 Expr *SimpleRefExpr = RefExpr;
3097 PrivateRefs.push_back(RefExpr);
3102 const DSAStackTy::DSAVarData DVar =
3104 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
3107 Clause->setPrivateRefs(PrivateRefs);
3111 for (
unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3119 DSAStackTy::DSAVarData DVar =
3125 Expr *MapExpr =
nullptr;
3127 DSAStack->checkMappableExprComponentListsForDecl(
3133 auto MI = MapExprComponents.rbegin();
3134 auto ME = MapExprComponents.rend();
3136 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3137 VD->getCanonicalDecl()) {
3138 MapExpr = MI->getAssociatedExpression();
3143 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3148 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3149 << MapExpr->getSourceRange();
3154 if (
const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3156 if (
auto *Clause = dyn_cast<OMPLastprivateClause>(
C)) {
3157 FinalizeLastprivate(Clause);
3158 }
else if (
auto *Clause = dyn_cast<OMPNontemporalClause>(
C)) {
3159 FinalizeNontemporal(Clause);
3160 }
else if (
auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
3161 FinalizeAllocators(Clause);
3176 Expr *NumIterations, Sema &SemaRef,
3177 Scope *S, DSAStackTy *Stack);
3180 OMPLoopBasedDirective::HelperExprs &B,
3181 DSAStackTy *Stack) {
3183 "loop exprs were not built");
3190 auto *LC = dyn_cast<OMPLinearClause>(
C);
3194 B.NumIterations, SemaRef,
3204class VarDeclFilterCCC final :
public CorrectionCandidateCallback {
3209 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3210 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3212 if (
const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3220 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3221 return std::make_unique<VarDeclFilterCCC>(*
this);
3225class VarOrFuncDeclFilterCCC final :
public CorrectionCandidateCallback {
3230 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3231 bool ValidateCandidate(
const TypoCorrection &Candidate)
override {
3241 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
3242 return std::make_unique<VarOrFuncDeclFilterCCC>(*
this);
3253 llvm::omp::Version OMPVersion =
getLangOpts().getOpenMPVersion();
3255 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3264 VarDeclFilterCCC CCC(
SemaRef);
3270 SemaRef.PDiag(Lookup.
empty() ? diag::err_undeclared_var_use_suggest
3271 : diag::err_omp_expected_var_arg_suggest)
3273 VD = Corrected.getCorrectionDeclAs<
VarDecl>();
3276 : diag::err_omp_expected_var_arg)
3289 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3291 Diag(Id.
getLoc(), diag::err_omp_global_var_arg)
3292 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->
isStaticLocal();
3296 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3307 !
SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3309 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3313 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3324 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3328 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3337 (!
SemaRef.getCurLexicalContext()->isFileContext() ||
3338 !
SemaRef.getCurLexicalContext()->Encloses(
3341 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3345 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3354 !
SemaRef.isDeclInScope(ND,
SemaRef.getCurLexicalContext(), CurScope)) {
3356 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3360 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3368 if ((Kind == OMPD_threadprivate && VD->
isUsed() &&
3370 (Kind == OMPD_groupprivate && VD->
isUsed())) {
3372 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3387 SemaRef.CurContext->addDecl(D);
3396 llvm::omp::Version OMPVersion =
getLangOpts().getOpenMPVersion();
3397 if (!OMPVersion || OMPVersion < 60) {
3398 Diag(Loc, diag::err_omp_unexpected_directive)
3399 << getOpenMPDirectiveName(OMPD_groupprivate, OMPVersion);
3403 SemaRef.CurContext->addDecl(D);
3410class LocalVarRefChecker final
3416 if (
const auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
3419 diag::err_omp_local_var_in_threadprivate_init)
3421 SemaRef.Diag(VD->
getLocation(), diag::note_defined_here)
3428 bool VisitStmt(
const Stmt *S) {
3429 for (
const Stmt *Child : S->
children()) {
3430 if (Child && Visit(Child))
3435 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3439OMPThreadPrivateDecl *
3444 for (
Expr *RefExpr : VarList) {
3462 if (
SemaRef.RequireCompleteType(
3463 ILoc, VD->
getType(), diag::err_omp_threadprivate_incomplete_type)) {
3470 llvm::omp::Version OMPVersion =
getLangOpts().getOpenMPVersion();
3471 Diag(ILoc, diag::err_omp_ref_type_arg)
3472 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3477 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3485 !(VD->
hasAttr<OMPThreadPrivateDeclAttr>() &&
3490 Diag(ILoc, diag::err_omp_var_thread_local)
3495 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3503 LocalVarRefChecker Checker(
SemaRef);
3504 if (Checker.Visit(
Init))
3508 Vars.push_back(RefExpr);
3509 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3510 VD->
addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3513 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3516 if (!Vars.empty()) {
3529 for (
Expr *RefExpr : VarList) {
3547 if (
SemaRef.RequireCompleteType(
3548 ILoc, VD->
getType(), diag::err_omp_groupprivate_incomplete_type)) {
3554 Diag(ILoc, diag::err_omp_ref_type_arg)
3555 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->
getType();
3559 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3567 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3572 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3577 Vars.push_back(RefExpr);
3578 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3579 VD->
addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3582 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3585 if (!Vars.empty()) {
3593static OMPAllocateDeclAttr::AllocatorTypeTy
3596 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3600 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3601 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3602 llvm::FoldingSetNodeID AEId;
3605 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3606 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
3607 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3608 llvm::FoldingSetNodeID DAEId;
3611 if (AEId == DAEId) {
3612 AllocatorKindRes = AllocatorKind;
3616 return AllocatorKindRes;
3621 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
Expr *Allocator) {
3622 if (!VD->
hasAttr<OMPAllocateDeclAttr>())
3624 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
3625 Expr *PrevAllocator = A->getAllocator();
3626 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3628 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3629 if (AllocatorsMatch &&
3630 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3631 Allocator && PrevAllocator) {
3634 llvm::FoldingSetNodeID AEId, PAEId;
3637 AllocatorsMatch = AEId == PAEId;
3639 if (!AllocatorsMatch) {
3641 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3645 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3647 PrevAllocator->printPretty(PrevAllocatorStream,
nullptr,
3655 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3657 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3658 S.
Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3659 << (Allocator ? 1 : 0) << AllocatorStream.str()
3660 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3662 S.
Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3663 << PrevAllocatorRange;
3671 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3673 if (VD->
hasAttr<OMPAllocateDeclAttr>())
3686 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.
Context, AllocatorKind,
3687 Allocator, Alignment, SR);
3690 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3696 assert(Clauses.size() <= 2 &&
"Expected at most two clauses.");
3697 Expr *Alignment =
nullptr;
3698 Expr *Allocator =
nullptr;
3699 if (Clauses.empty()) {
3705 !
DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3706 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3709 if (
const auto *AC = dyn_cast<OMPAllocatorClause>(
C))
3710 Allocator = AC->getAllocator();
3711 else if (
const auto *AC = dyn_cast<OMPAlignClause>(
C))
3712 Alignment = AC->getAlignment();
3714 llvm_unreachable(
"Unexpected clause on allocate directive");
3716 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3719 for (
Expr *RefExpr : VarList) {
3725 VD->
hasAttr<OMPThreadPrivateDeclAttr>() ||
3733 AllocatorKind, Allocator))
3741 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3743 diag::err_omp_expected_predefined_allocator)
3748 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3754 Vars.push_back(RefExpr);
3761 Owner =
SemaRef.getCurLexicalContext();
3772 if (!
SemaRef.CurContext->isFileContext()) {
3773 Diag(Loc, diag::err_omp_invalid_scope) <<
"requires";
3777 SemaRef.CurContext->addDecl(D);
3787 bool SkippedClauses) {
3788 if (!SkippedClauses && Assumptions.empty()) {
3789 llvm::omp::Version OMPVersion =
getLangOpts().getOpenMPVersion();
3790 Diag(Loc, diag::err_omp_no_clause_for_directive)
3791 << llvm::omp::getAllAssumeClauseOptions()
3792 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3796 OMPAssumeAttr::Create(
getASTContext(), llvm::join(Assumptions,
","), Loc);
3797 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3798 OMPAssumeScoped.push_back(AA);
3803 if (Assumptions.empty())
3806 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3807 "Unexpected omp assumption directive!");
3808 OMPAssumeGlobal.push_back(AA);
3815 auto *Ctx =
SemaRef.CurContext;
3816 while (Ctx->getLexicalParent())
3817 Ctx = Ctx->getLexicalParent();
3818 DeclContexts.push_back(Ctx);
3819 while (!DeclContexts.empty()) {
3821 for (
auto *SubDC : DC->
decls()) {
3822 if (SubDC->isInvalidDecl())
3824 if (
auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3825 DeclContexts.push_back(CTD->getTemplatedDecl());
3826 llvm::append_range(DeclContexts, CTD->specializations());
3829 if (
auto *DC = dyn_cast<DeclContext>(SubDC))
3830 DeclContexts.push_back(DC);
3831 if (
auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3841 OMPAssumeScoped.pop_back();
3859 bool HasImplicitOtherwise = Variants.size() == TraitInfos.size() + 1;
3860 assert((HasImplicitOtherwise || Variants.size() == TraitInfos.size()) &&
3861 "Expected one variant per metadirective clause");
3863 if (HasImplicitOtherwise)
3864 AllTraitInfos.push_back(&
getASTContext().getNewOMPTraitInfo());
3868 Expr *Cond =
nullptr;
3869 TI->anyScoreOrCondition([&](
Expr *&E,
bool IsScore) {
3878 Cond =
SemaRef.MakeFullExpr(Val.
get()).get();
3880 Conditions.push_back(Cond);
3883 Conditions, AllTraitInfos,
3884 HasImplicitOtherwise);
3894 DSAStack->getEncounteredTargetLocs();
3896 if (!TargetLocations.empty() || !AtomicLoc.
isInvalid()) {
3897 for (
const OMPClause *CNew : ClauseList) {
3903 Diag(Loc, diag::err_omp_directive_before_requires)
3906 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3911 Diag(Loc, diag::err_omp_directive_before_requires)
3913 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3919 if (!
DSAStack->hasDuplicateRequiresClause(ClauseList))
3927 const DSAStackTy::DSAVarData &DVar,
3928 bool IsLoopIterVar) {
3930 SemaRef.
Diag(DVar.RefExpr->
getExprLoc(), diag::note_omp_explicit_dsa)
3935 PDSA_StaticMemberShared,
3936 PDSA_StaticLocalVarShared,
3937 PDSA_LoopIterVarPrivate,
3938 PDSA_LoopIterVarLinear,
3939 PDSA_LoopIterVarLastprivate,
3940 PDSA_ConstVarShared,
3941 PDSA_GlobalVarShared,
3942 PDSA_TaskVarFirstprivate,
3943 PDSA_LocalVarPrivate,
3945 } Reason = PDSA_Implicit;
3946 bool ReportHint =
false;
3948 auto *VD = dyn_cast<VarDecl>(D);
3949 if (IsLoopIterVar) {
3950 if (DVar.CKind == OMPC_private)
3951 Reason = PDSA_LoopIterVarPrivate;
3952 else if (DVar.CKind == OMPC_lastprivate)
3953 Reason = PDSA_LoopIterVarLastprivate;
3955 Reason = PDSA_LoopIterVarLinear;
3957 DVar.CKind == OMPC_firstprivate) {
3958 Reason = PDSA_TaskVarFirstprivate;
3959 ReportLoc = DVar.ImplicitDSALoc;
3961 Reason = PDSA_StaticLocalVarShared;
3963 Reason = PDSA_StaticMemberShared;
3965 Reason = PDSA_GlobalVarShared;
3967 Reason = PDSA_ConstVarShared;
3968 else if (VD && VD->
isLocalVarDecl() && DVar.CKind == OMPC_private) {
3970 Reason = PDSA_LocalVarPrivate;
3972 if (Reason != PDSA_Implicit) {
3974 SemaRef.
Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3975 << Reason << ReportHint
3976 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3977 }
else if (DVar.ImplicitDSALoc.
isValid()) {
3978 SemaRef.
Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3986 llvm::SmallPtrSet<const VarDecl *, 8> &UsedVars;
3987 llvm::SmallPtrSet<const BindingDecl *, 8> &UsedBindings;
3990 VarUsageVisitor(llvm::SmallPtrSet<const VarDecl *, 8> &UsedVars,
3991 llvm::SmallPtrSet<const BindingDecl *, 8> &UsedBindings)
3992 : UsedVars(UsedVars), UsedBindings(UsedBindings) {}
3994 bool VisitDeclRefExpr(DeclRefExpr *DRE)
override {
3995 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
3997 else if (
auto *BD = dyn_cast<BindingDecl>(DRE->
getDecl()))
4012 std::pair<bool, SourceLocation>, 4> &SeenDecompositions,
4014 const auto *BD = dyn_cast<BindingDecl>(D);
4018 const auto *DD = dyn_cast<DecompositionDecl>(BD->getDecomposedDecl());
4023 bool IsByRef =
false;
4024 switch (ClauseKind) {
4030 case OMPC_firstprivate:
4032 case OMPC_lastprivate:
4040 auto [It, Inserted] = SeenDecompositions.insert({DD, {IsByRef, ELoc}});
4041 if (!Inserted && It->second.first != IsByRef) {
4045 diag::err_omp_decomposition_bindings_different_capture_kinds)
4060 Stmt *Body =
nullptr) {
4062 std::pair<bool, SourceLocation>, 4>
4065 bool HasError =
false;
4066 bool HasDefaultShared =
false;
4069 if (
auto *DC = dyn_cast<OMPDefaultClause>(
C)) {
4070 if (DC->getDefaultKind() == llvm::omp::DefaultKind::OMP_DEFAULT_shared) {
4071 HasDefaultShared =
true;
4072 DefaultSharedLoc = DC->getBeginLoc();
4077 if (CK != OMPC_map && CK != OMPC_firstprivate && CK != OMPC_private &&
4078 CK != OMPC_shared && CK != OMPC_lastprivate)
4081 if (
auto *MPC = dyn_cast<OMPMapClause>(
C))
4082 Varlist = MPC->varlist();
4083 else if (
auto *FPC = dyn_cast<OMPFirstprivateClause>(
C))
4084 Varlist = FPC->varlist();
4085 else if (
auto *PC = dyn_cast<OMPPrivateClause>(
C))
4086 Varlist = PC->varlist();
4087 else if (
auto *SC = dyn_cast<OMPSharedClause>(
C))
4088 Varlist = SC->varlist();
4089 else if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C))
4090 Varlist = LPC->varlist();
4092 for (
Expr *
VE : Varlist) {
4093 if (
auto *DRE = dyn_cast<DeclRefExpr>(
VE->IgnoreParenImpCasts())) {
4098 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(D)) {
4100 dyn_cast<DeclRefExpr>(CED->getInit()->IgnoreParenImpCasts()))
4101 D = InitDRE->getDecl();
4103 if (
auto *BD = dyn_cast<BindingDecl>(D))
4106 SemaRef, DKind, SeenDecompositions, D,
VE->getExprLoc(), CK))
4115 if (HasDefaultShared && Body) {
4118 VarUsageVisitor Visitor(UsedVars, UsedBindings);
4119 Visitor.TraverseStmt(Body);
4121 if (ExplicitBindings.contains(BD))
4124 BD, DefaultSharedLoc, OMPC_shared))
4135 llvm::SmallDenseMap<const VarDecl *, SourceLocation, 4> MappedOrigVars;
4138 if (
auto *MPC = dyn_cast<OMPMapClause>(
C)) {
4139 for (
Expr *
VE : MPC->varlist()) {
4140 if (
auto *DRE = dyn_cast<DeclRefExpr>(
VE->IgnoreParenImpCasts())) {
4141 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl())) {
4148 if (MappedOrigVars.empty())
4153 VarUsageVisitor Visitor(UsedVars, UsedBindings);
4154 Visitor.TraverseStmt(Body);
4155 bool HasError =
false;
4156 for (
const auto &Entry : MappedOrigVars) {
4157 const VarDecl *OrigVar = Entry.first;
4163 bool BindingsFromThisVarUsed =
false;
4165 if (
auto *DD = dyn_cast<DecompositionDecl>(BD->getDecomposedDecl())) {
4166 if (DD->getType()->isReferenceType())
4168 if (
auto *OrigFromDD = DD->getOriginalVar().Var) {
4169 if (OrigFromDD->getCanonicalDecl() == OrigVar) {
4170 BindingsFromThisVarUsed =
true;
4179 if (BindingsFromThisVarUsed && !UsedVars.count(OrigVar)) {
4180 SemaRef.
Diag(Loc, diag::err_omp_original_var_mapped_bindings_only_used)
4191 bool IsAggregateOrDeclareTarget,
4192 bool HasConstQualifier) {
4195 case OMPC_DEFAULTMAP_MODIFIER_alloc:
4196 case OMPC_DEFAULTMAP_MODIFIER_storage:
4197 Kind = OMPC_MAP_alloc;
4199 case OMPC_DEFAULTMAP_MODIFIER_to:
4202 case OMPC_DEFAULTMAP_MODIFIER_from:
4203 Kind = OMPC_MAP_from;
4205 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
4206 Kind = OMPC_MAP_tofrom;
4208 case OMPC_DEFAULTMAP_MODIFIER_present:
4214 Kind = OMPC_MAP_alloc;
4216 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
4217 case OMPC_DEFAULTMAP_MODIFIER_private:
4219 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
4220 case OMPC_DEFAULTMAP_MODIFIER_none:
4221 case OMPC_DEFAULTMAP_MODIFIER_default:
4226 if (IsAggregateOrDeclareTarget) {
4227 if (HasConstQualifier)
4230 Kind = OMPC_MAP_tofrom;
4233 llvm_unreachable(
"Unexpected defaultmap implicit behavior");
4240 for (
const auto *FD : RD->
fields()) {
4254 while (
T->isArrayType())
4255 T =
T->getAsArrayTypeUnsafe()->getElementType();
4256 if (!
T.isConstQualified())
4258 if (
const auto *RD =
T->getAsCXXRecordDecl())
4273static const VarDecl *getOriginalVarOrDiagnose(Sema &S,
4274 const DecompositionDecl *DD,
4275 SourceLocation Loc) {
4278 S.
Diag(Loc, diag::err_omp_unsupported_structured_binding_init)
4283struct VariableImplicitInfo {
4288 llvm::SetVector<Expr *> Firstprivates;
4289 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
4290 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
4291 MapModifiers[DefaultmapKindNum];
4294class DSAAttrChecker final :
public StmtVisitor<DSAAttrChecker, void> {
4298 bool ErrorFound =
false;
4299 bool TryCaptureCXXThisMembers =
false;
4300 CapturedStmt *CS =
nullptr;
4302 VariableImplicitInfo ImpInfo;
4304 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
4306 void VisitSubCaptures(OMPExecutableDirective *S) {
4308 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
4310 if (S->getDirectiveKind() == OMPD_atomic ||
4311 S->getDirectiveKind() == OMPD_critical ||
4312 S->getDirectiveKind() == OMPD_section ||
4313 S->getDirectiveKind() == OMPD_master ||
4314 S->getDirectiveKind() == OMPD_masked ||
4315 S->getDirectiveKind() == OMPD_scope ||
4316 S->getDirectiveKind() == OMPD_assume ||
4318 Visit(S->getAssociatedStmt());
4321 visitSubCaptures(S->getInnermostCapturedStmt());
4324 if (TryCaptureCXXThisMembers ||
4326 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
4327 [](
const CapturedStmt::Capture &
C) {
4328 return C.capturesThis();
4330 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
4331 TryCaptureCXXThisMembers =
true;
4332 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
4333 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
4339 for (OMPClause *
C : S->clauses())
4340 if (
auto *FC = dyn_cast<OMPFirstprivateClause>(
C)) {
4341 for (Expr *Ref : FC->varlist())
4348 void VisitDeclRefExpr(DeclRefExpr *E) {
4354 ValueDecl *D =
const_cast<ValueDecl *
>(E->
getDecl());
4355 BindingDecl *BD = dyn_cast<BindingDecl>(D);
4358 if (
auto *VD = dyn_cast<VarDecl>(D)) {
4361 ValueDecl *LookupDecl = BD ?
static_cast<ValueDecl *
>(BD) : VD;
4364 !Stack->getTopDSA(LookupDecl,
false).RefExpr &&
4365 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
4366 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
4367 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
4368 Visit(
const_cast<Expr *
>(CED->getInit()));
4374 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
4389 bool InTargetAndScalar = BD &&
4394 (!InTargetAndScalar && !isImplicitOrExplicitTaskingRegion(DKind) &&
4402 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4403 !Stack->isImplicitTaskFirstprivate(VD))
4406 if (Stack->isUsesAllocatorsDecl(VD))
4409 DSAStackTy::DSAVarData DVar =
4410 Stack->getTopDSA(LookupDecl,
false);
4412 if (BD && !DVar.RefExpr)
4413 DVar = Stack->getTopDSA(VD,
false);
4416 !ImplicitDeclarations
4422 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4423 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4425 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4426 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4427 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4428 !Stack->isImplicitTaskFirstprivate(VD))
4436 if (DVar.CKind == OMPC_unknown &&
4437 (Stack->getDefaultDSA() == DSA_none ||
4438 Stack->getDefaultDSA() == DSA_private ||
4439 Stack->getDefaultDSA() == DSA_firstprivate) &&
4440 isImplicitOrExplicitTaskingRegion(DKind) &&
4441 VarsWithInheritedDSA.count(VD) == 0) {
4442 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4443 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4444 Stack->getDefaultDSA() == DSA_private)) {
4445 DSAStackTy::DSAVarData DVar =
4446 Stack->getImplicitDSA(LookupDecl,
false);
4447 if (BD && DVar.CKind == OMPC_unknown)
4448 DVar = Stack->getImplicitDSA(VD,
false);
4449 InheritedDSA = DVar.CKind == OMPC_unknown;
4454 if (Stack->getDefaultDSA() == DSA_none)
4468 SemaRef.
getLangOpts(), BD ?
static_cast<const ValueDecl *
>(BD)
4469 :
static_cast<const ValueDecl *
>(VD));
4471 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4472 OMPC_DEFAULTMAP_MODIFIER_none;
4473 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4474 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4478 if (!Stack->checkMappableExprComponentListsForDecl(
4483 auto MI = MapExprComponents.rbegin();
4484 auto ME = MapExprComponents.rend();
4485 return MI != ME && MI->getAssociatedDeclaration() == VD;
4494 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4495 OMPC_DEFAULTMAP_MODIFIER_present;
4496 if (IsModifierPresent) {
4497 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4498 OMPC_MAP_MODIFIER_present)) {
4499 ImpInfo.MapModifiers[ClauseKind].push_back(
4500 OMPC_MAP_MODIFIER_present);
4506 !Stack->isLoopControlVariable(VD).first) {
4510 bool AlreadyMapped = Stack->checkMappableExprComponentListsForDecl(
4511 VD,
true, [
this](
auto StackComponents,
auto) {
4513 return !StackComponents.empty();
4516 return StackComponents.size() == 1 ||
4518 llvm::drop_begin(llvm::reverse(StackComponents)),
4519 [](
const auto &MC) {
4520 return MC.getAssociatedDeclaration() ==
nullptr &&
4522 MC.getAssociatedExpression()) ||
4524 MC.getAssociatedExpression()) ||
4526 MC.getAssociatedExpression()));
4532 const auto *DD = dyn_cast<DecompositionDecl>(VD);
4533 if (!AlreadyMapped && DD) {
4537 AlreadyMapped = Stack->checkMappableExprComponentListsForDecl(
4539 [
this](
auto StackComponents,
auto) {
4541 return !StackComponents.empty();
4542 return StackComponents.size() == 1;
4546 if (!AlreadyMapped) {
4547 bool IsFirstprivate =
false;
4550 if (
const auto *RD =
4552 IsFirstprivate = RD->isLambda();
4554 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4555 if (IsFirstprivate) {
4556 ImpInfo.Firstprivates.insert(E);
4559 Stack->getDefaultmapModifier(ClauseKind);
4560 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4561 ImpInfo.Privates.insert(E);
4564 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
4566 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4577 DVar = Stack->hasInnermostDSA(
4580 return C == OMPC_reduction && !AppliedToPointee;
4589 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4595 DVar = Stack->getImplicitDSA(LookupDecl,
false);
4596 if (BD && DVar.CKind == OMPC_unknown)
4597 DVar = Stack->getImplicitDSA(VD,
false);
4599 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4600 DVar.CKind == OMPC_firstprivate) ||
4601 (Stack->getDefaultDSA() == DSA_private &&
4602 DVar.CKind == OMPC_private)) &&
4604 !Stack->isLoopControlVariable(VD).first) {
4605 if (Stack->getDefaultDSA() == DSA_private)
4606 ImpInfo.Privates.insert(E);
4608 ImpInfo.Firstprivates.insert(E);
4615 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4616 Stack->addToParentTargetRegionLinkGlobals(E);
4621 void VisitMemberExpr(MemberExpr *E) {
4629 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD,
false);
4632 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4636 !Stack->isLoopControlVariable(FD).first &&
4637 !Stack->checkMappableExprComponentListsForDecl(
4642 return isa<CXXThisExpr>(
4644 StackComponents.back().getAssociatedExpression())
4656 if (Stack->isClassPreviouslyMapped(TE->getType()))
4660 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4666 ImpInfo.Mappings[ClauseKind][
Kind].insert(E);
4675 DVar = Stack->hasInnermostDSA(
4678 return C == OMPC_reduction && !AppliedToPointee;
4687 SemaRef.
Diag(ELoc, diag::err_omp_reduction_in_task);
4693 DVar = Stack->getImplicitDSA(FD,
false);
4695 !Stack->isLoopControlVariable(FD).first) {
4700 if (DVar.CKind != OMPC_unknown)
4701 ImpInfo.Firstprivates.insert(E);
4711 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4712 if (!Stack->checkMappableExprComponentListsForDecl(
4718 auto CCI = CurComponents.rbegin();
4719 auto CCE = CurComponents.rend();
4720 for (const auto &SC : llvm::reverse(StackComponents)) {
4722 if (CCI->getAssociatedExpression()->getStmtClass() !=
4723 SC.getAssociatedExpression()->getStmtClass())
4724 if (!((isa<ArraySectionExpr>(
4725 SC.getAssociatedExpression()) ||
4726 isa<OMPArrayShapingExpr>(
4727 SC.getAssociatedExpression())) &&
4728 isa<ArraySubscriptExpr>(
4729 CCI->getAssociatedExpression())))
4732 const Decl *CCD = CCI->getAssociatedDeclaration();
4733 const Decl *SCD = SC.getAssociatedDeclaration();
4734 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4735 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4738 std::advance(CCI, 1);
4746 }
else if (!TryCaptureCXXThisMembers) {
4750 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4751 for (OMPClause *
C : S->clauses()) {
4754 if (isa_and_nonnull<OMPPrivateClause>(
C))
4762 for (Stmt *CC :
C->children()) {
4769 VisitSubCaptures(S);
4772 void VisitOMPCanonicalLoopNestTransformationDirective(
4773 OMPCanonicalLoopNestTransformationDirective *S) {
4780 void VisitOMPMetaDirective(OMPMetaDirective *S) { VisitStmt(S); }
4782 void VisitCallExpr(CallExpr *S) {
4791 auto *CI =
Callee->IgnoreParenImpCasts();
4792 if (
auto *CE = dyn_cast<MemberExpr>(CI))
4793 Visit(CE->getBase());
4794 else if (
auto *CE = dyn_cast<DeclRefExpr>(CI))
4798 void VisitStmt(Stmt *S) {
4808 void visitSubCaptures(CapturedStmt *S) {
4809 for (
const CapturedStmt::Capture &Cap : S->
captures()) {
4810 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4812 VarDecl *VD = Cap.getCapturedVar();
4816 Stack->checkMappableExprComponentListsForDecl(
4823 Cap.getLocation(),
true);
4827 bool isErrorFound()
const {
return ErrorFound; }
4828 const VariableImplicitInfo &getImplicitInfo()
const {
return ImpInfo; }
4830 return VarsWithInheritedDSA;
4833 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4834 : Stack(S), SemaRef(SemaRef), ErrorFound(
false), CS(CS) {
4835 DKind = S->getCurrentDirective();
4838 for (DeclRefExpr *E : Stack->getLinkGlobals())
4850 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4852 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4854 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4856 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4858 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4859 Stack->handleConstructTrait(Traits, ScopeEntry);
4862static SmallVector<SemaOpenMP::CapturedParamNameType>
4866 Context.getIntTypeForBitwidth(32, 1).
withConst();
4870 std::make_pair(
".global_tid.", KmpInt32PtrTy),
4871 std::make_pair(
".bound_tid.", KmpInt32PtrTy),
4873 if (LoopBoundSharing) {
4875 Params.push_back(std::make_pair(
".previous.lb.", KmpSizeTy));
4876 Params.push_back(std::make_pair(
".previous.ub.", KmpSizeTy));
4880 Params.push_back(std::make_pair(StringRef(),
QualType()));
4884static SmallVector<SemaOpenMP::CapturedParamNameType>
4889static SmallVector<SemaOpenMP::CapturedParamNameType>
4899 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4901 std::make_pair(
".global_tid.", KmpInt32Ty),
4902 std::make_pair(
".part_id.", KmpInt32PtrTy),
4903 std::make_pair(
".privates.", VoidPtrTy),
4906 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4907 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4908 std::make_pair(StringRef(),
QualType())
4913static SmallVector<SemaOpenMP::CapturedParamNameType>
4918 Params.push_back(std::make_pair(StringRef(),
QualType()));
4922 Params.push_back(std::make_pair(StringRef(
"dyn_ptr"), VoidPtrTy));
4926static SmallVector<SemaOpenMP::CapturedParamNameType>
4929 std::make_pair(StringRef(),
QualType())
4934static SmallVector<SemaOpenMP::CapturedParamNameType>
4938 Context.getIntTypeForBitwidth(32, 1).
withConst();
4940 Context.getIntTypeForBitwidth(64, 0).
withConst();
4942 Context.getIntTypeForBitwidth(64, 1).
withConst();
4949 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4951 std::make_pair(
".global_tid.", KmpInt32Ty),
4952 std::make_pair(
".part_id.", KmpInt32PtrTy),
4953 std::make_pair(
".privates.", VoidPtrTy),
4956 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4957 std::make_pair(
".task_t.", Context.VoidPtrTy.withConst()),
4958 std::make_pair(
".lb.", KmpUInt64Ty),
4959 std::make_pair(
".ub.", KmpUInt64Ty),
4960 std::make_pair(
".st.", KmpInt64Ty),
4961 std::make_pair(
".liter.", KmpInt32Ty),
4962 std::make_pair(
".reductions.", VoidPtrTy),
4963 std::make_pair(StringRef(),
QualType())
4976 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4977 SemaRef.
getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4980 for (
auto [Level, RKind] : llvm::enumerate(Regions)) {
5015 case OMPD_metadirective:
5018 llvm_unreachable(
"Unexpected capture region");
5025 if (DKind == OMPD_ordered_blockassoc &&
5026 DSAStack->getCurrentDirective() == OMPD_ordered_standalone) {
5027 DSAStack->setOrderedToBlockAssociated();
5040 case OMPD_interchange:
5055int SemaOpenMP::getNumberOfConstructScopes(
unsigned Level)
const {
5056 return getOpenMPCaptureLevels(
DSAStack->getDirective(Level));
5062 return CaptureRegions.size();
5066 Expr *CaptureExpr,
bool WithInit,
5068 bool AsExpression) {
5069 assert(CaptureExpr);
5075 Ty =
C.getLValueReferenceType(Ty);
5077 Ty =
C.getPointerType(Ty);
5089 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(
C));
5148class CaptureRegionUnwinderRAII {
5155 CaptureRegionUnwinderRAII(Sema &S,
bool &ErrorFound,
5157 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
5158 ~CaptureRegionUnwinderRAII() {
5161 while (--ThisCaptureLevel >= 0)
5171 if (!
SemaRef.CurContext->isDependentContext() &&
5174 DSAStack->getCurrentDirective()))) {
5176 if (
const auto *RD =
Type.getCanonicalType()
5177 .getNonReferenceType()
5179 bool SavedForceCaptureByReferenceInTargetExecutable =
5180 DSAStack->isForceCaptureByReferenceInTargetExecutable();
5181 DSAStack->setForceCaptureByReferenceInTargetExecutable(
5183 if (RD->isLambda()) {
5184 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
5186 RD->getCaptureFields(Captures, ThisCapture);
5193 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
5194 }
else if (LC.getCaptureKind() ==
LCK_This) {
5197 ThisTy, ThisCapture->
getType()))
5198 SemaRef.CheckCXXThisCapture(LC.getLocation());
5202 DSAStack->setForceCaptureByReferenceInTargetExecutable(
5203 SavedForceCaptureByReferenceInTargetExecutable);
5210 const OMPOrderedClause *Ordered =
nullptr;
5213 for (
const OMPClause *Clause : Clauses) {
5214 if (Clause->getClauseKind() == OMPC_ordered)
5216 else if (Clause->getClauseKind() == OMPC_order) {
5218 if (Order->
getKind() != OMPC_ORDER_concurrent)
5221 if (Ordered && Order)
5225 if (Ordered && Order) {
5227 diag::err_omp_simple_clause_incompatible_with_ordered)
5230 <<
SourceRange(Order->getBeginLoc(), Order->getEndLoc());
5231 S.
Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
5232 << 0 <<
SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
5245 bool ErrorFound =
false;
5246 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
5255 OMPOrderedClause *OC =
nullptr;
5256 OMPScheduleClause *SC =
nullptr;
5263 DSAStack->getCurrentDirective() == OMPD_target) &&
5264 Clause->getClauseKind() == OMPC_in_reduction) {
5268 for (
Expr *E : IRC->taskgroup_descriptors())
5270 SemaRef.MarkDeclarationsReferencedInExpr(E);
5273 Clause->getClauseKind() == OMPC_copyprivate ||
5276 Clause->getClauseKind() == OMPC_copyin)) {
5277 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
5280 if (
auto *E = cast_or_null<Expr>(VarRef)) {
5281 SemaRef.MarkDeclarationsReferencedInExpr(E);
5284 DSAStack->setForceVarCapturing(
false);
5285 }
else if (CaptureRegions.size() > 1 ||
5286 CaptureRegions.back() != OMPD_unknown) {
5290 if (
Expr *E =
C->getPostUpdateExpr())
5291 SemaRef.MarkDeclarationsReferencedInExpr(E);
5294 if (Clause->getClauseKind() == OMPC_schedule)
5296 else if (Clause->getClauseKind() == OMPC_ordered)
5298 else if (Clause->getClauseKind() == OMPC_linear)
5303 SemaRef.MarkDeclarationsReferencedInExpr(E);
5308 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
5309 SC->getSecondScheduleModifier() ==
5310 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
5312 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
5313 ? SC->getFirstScheduleModifierLoc()
5314 : SC->getSecondScheduleModifierLoc(),
5315 diag::err_omp_simple_clause_incompatible_with_ordered)
5318 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
5319 <<
SourceRange(OC->getBeginLoc(), OC->getEndLoc());
5327 if (!LCs.empty() && OC && OC->getNumForLoops()) {
5328 for (
const OMPLinearClause *
C : LCs) {
5329 Diag(
C->getBeginLoc(), diag::err_omp_linear_ordered)
5330 <<
SourceRange(OC->getBeginLoc(), OC->getEndLoc());
5336 OC->getNumForLoops()) {
5337 llvm::omp::Version OMPVersion =
getLangOpts().getOpenMPVersion();
5338 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
5339 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(), OMPVersion);
5346 unsigned CompletedRegions = 0;
5351 if (ThisCaptureRegion != OMPD_unknown) {
5359 if (CaptureRegion == ThisCaptureRegion ||
5360 CaptureRegion == OMPD_unknown) {
5361 if (
auto *DS = cast_or_null<DeclStmt>(
C->getPreInitStmt())) {
5362 for (
Decl *D : DS->decls())
5369 if (ThisCaptureRegion == OMPD_target) {
5373 if (
const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(
C)) {
5374 for (
unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
5378 SemaRef.MarkDeclarationsReferencedInExpr(E);
5384 if (ThisCaptureRegion == OMPD_parallel) {
5388 if (
auto *RC = dyn_cast<OMPReductionClause>(
C)) {
5389 if (RC->getModifier() != OMPC_REDUCTION_inscan)
5391 for (
Expr *E : RC->copy_array_temps())
5393 SemaRef.MarkDeclarationsReferencedInExpr(E);
5395 if (
auto *AC = dyn_cast<OMPAlignedClause>(
C)) {
5396 for (
Expr *E : AC->varlist())
5397 SemaRef.MarkDeclarationsReferencedInExpr(E);
5401 if (++CompletedRegions == CaptureRegions.size())
5403 SR =
SemaRef.ActOnCapturedRegionEnd(SR.
get());
5412 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
5415 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
5416 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
5420 SemaRef.
Diag(StartLoc, diag::err_omp_wrong_cancel_region)
5421 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
5431 if (!Stack->getCurScope())
5436 bool NestingProhibited =
false;
5437 bool CloseNesting =
true;
5438 bool OrphanSeen =
false;
5441 ShouldBeInParallelRegion,
5442 ShouldBeInOrderedRegion,
5443 ShouldBeInTargetRegion,
5444 ShouldBeInTeamsRegion,
5445 ShouldBeInLoopSimdRegion,
5446 } Recommend = NoRecommend;
5450 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
5454 if (OMPVersion >= 50 && Stack->isEnclosingOrderConcurrent() &&
5457 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_order)
5458 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5463 if (Stack->isInSimdRegion() &&
5464 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered_blockassoc) ||
5466 CurrentRegion, BindKind, SemaRef.
LangOpts)))) {
5483 SemaRef.
Diag(StartLoc, (CurrentRegion != OMPD_simd)
5484 ? diag::err_omp_prohibited_region_simd
5485 : diag::warn_omp_nesting_simd)
5486 << (OMPVersion >= 60 ? 2
5487 : OMPVersion >= 50 ? 1
5489 return CurrentRegion != OMPD_simd;
5491 if (EnclosingConstruct == OMPD_atomic) {
5494 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5497 if (CurrentRegion == OMPD_section) {
5502 if (EnclosingConstruct != OMPD_sections) {
5503 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5504 << (ParentRegion != OMPD_unknown)
5505 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5513 if (ParentRegion == OMPD_unknown &&
5515 CurrentRegion != OMPD_cancellation_point &&
5516 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5520 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5521 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5523 EnclosingConstruct == OMPD_loop)) {
5524 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5525 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5526 <<
true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5527 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5530 if (CurrentRegion == OMPD_cancellation_point ||
5531 CurrentRegion == OMPD_cancel) {
5544 if (CancelRegion == OMPD_taskgroup) {
5546 EnclosingConstruct != OMPD_task &&
5547 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5548 }
else if (CancelRegion == OMPD_sections) {
5549 NestingProhibited = EnclosingConstruct != OMPD_section &&
5550 EnclosingConstruct != OMPD_sections;
5552 NestingProhibited = CancelRegion != Leafs.back();
5554 OrphanSeen = ParentRegion == OMPD_unknown;
5555 }
else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5562 }
else if (CurrentRegion == OMPD_critical && CurrentName.
getName()) {
5568 bool DeadLock = Stack->hasDirective(
5572 if (K == OMPD_critical && DNI.
getName() == CurrentName.
getName()) {
5573 PreviousCriticalLoc = Loc;
5580 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5582 if (PreviousCriticalLoc.
isValid())
5583 SemaRef.
Diag(PreviousCriticalLoc,
5584 diag::note_omp_previous_critical_region);
5587 }
else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5599 {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5600 EnclosingConstruct);
5613 {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5614 EnclosingConstruct);
5615 Recommend = ShouldBeInParallelRegion;
5616 }
else if (CurrentRegion == OMPD_ordered_blockassoc ||
5617 CurrentRegion == OMPD_ordered_standalone) {
5626 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5629 Stack->isParentOrderedRegion());
5630 Recommend = ShouldBeInOrderedRegion;
5636 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5637 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5638 EnclosingConstruct != OMPD_target);
5639 OrphanSeen = ParentRegion == OMPD_unknown;
5640 Recommend = ShouldBeInTargetRegion;
5641 }
else if (CurrentRegion == OMPD_scan) {
5642 if (OMPVersion >= 50) {
5647 NestingProhibited = !llvm::is_contained(
5648 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5650 NestingProhibited =
true;
5652 OrphanSeen = ParentRegion == OMPD_unknown;
5653 Recommend = ShouldBeInLoopSimdRegion;
5657 EnclosingConstruct == OMPD_teams) {
5669 CurrentRegion != OMPD_loop &&
5671 CurrentRegion == OMPD_atomic);
5672 Recommend = ShouldBeInParallelRegion;
5674 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5680 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5681 Recommend = ShouldBeInTeamsRegion;
5687 NestingProhibited = EnclosingConstruct != OMPD_teams;
5688 Recommend = ShouldBeInTeamsRegion;
5690 if (!NestingProhibited &&
5697 NestingProhibited = Stack->hasDirective(
5701 OffendingRegion = K;
5707 CloseNesting =
false;
5709 if (NestingProhibited) {
5711 SemaRef.
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5712 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5714 SemaRef.
Diag(StartLoc, diag::err_omp_prohibited_region)
5715 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5716 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5730 bool ErrorFound =
false;
5731 unsigned NamedModifiersNumber = 0;
5732 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5733 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5737 if (
const auto *IC = dyn_cast_or_null<OMPIfClause>(
C)) {
5741 auto &FNM = FoundNameModifiers[CurNM];
5743 S.
Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
5744 << getOpenMPDirectiveName(Kind, OMPVersion)
5746 << getOpenMPDirectiveName(CurNM, OMPVersion);
5748 }
else if (CurNM != OMPD_unknown) {
5749 NameModifierLoc.push_back(IC->getNameModifierLoc());
5750 ++NamedModifiersNumber;
5753 if (CurNM == OMPD_unknown)
5759 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5760 S.
Diag(IC->getNameModifierLoc(),
5761 diag::err_omp_wrong_if_directive_name_modifier)
5762 << getOpenMPDirectiveName(CurNM, OMPVersion)
5763 << getOpenMPDirectiveName(Kind, OMPVersion);
5770 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5771 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5772 S.
Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5773 diag::err_omp_no_more_if_clause);
5776 std::string Sep(
", ");
5777 unsigned AllowedCnt = 0;
5778 unsigned TotalAllowedNum =
5779 AllowedNameModifiers.size() - NamedModifiersNumber;
5780 for (
unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5783 if (!FoundNameModifiers[NM]) {
5785 Values += getOpenMPDirectiveName(NM, OMPVersion);
5787 if (AllowedCnt + 2 == TotalAllowedNum)
5789 else if (AllowedCnt + 1 != TotalAllowedNum)
5794 S.
Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5795 diag::err_omp_unnamed_if_clause)
5796 << (TotalAllowedNum > 1) << Values;
5799 S.
Diag(Loc, diag::note_omp_previous_named_if_clause);
5806static std::pair<ValueDecl *, bool>
5809 bool AllowAssumedSizeArray, StringRef DiagType) {
5812 return std::make_pair(
nullptr,
true);
5838 } IsArrayExpr = NoArrayExpr;
5839 if (AllowArraySection) {
5840 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5841 Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
5842 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5843 Base = TempASE->getBase()->IgnoreParenImpCasts();
5846 }
else if (
auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5847 Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
5848 if (S.
getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5849 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5851 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5852 !BaseType->isVariableArrayType())) {
5853 S.
Diag(OASE->getColonLocFirst(),
5854 diag::err_omp_section_length_undefined)
5855 << (!BaseType.isNull() && BaseType->isArrayType());
5856 return std::make_pair(
nullptr,
false);
5859 while (
auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
5860 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5861 while (
auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
5862 Base = TempASE->getBase()->IgnoreParenImpCasts();
5864 IsArrayExpr = OMPArraySection;
5870 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5871 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5876 if (IsArrayExpr != NoArrayExpr) {
5877 S.
Diag(ELoc, diag::err_omp_expected_base_var_name)
5878 << IsArrayExpr << ERange;
5879 }
else if (!DiagType.empty()) {
5883 S.
Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5884 << DiagSelect << DiagType << ERange;
5888 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5889 : diag::err_omp_expected_var_name_member_expr)
5892 return std::make_pair(
nullptr,
false);
5894 return std::make_pair(
5901class AllocatorChecker final :
public ConstStmtVisitor<AllocatorChecker, bool> {
5902 DSAStackTy *S =
nullptr;
5905 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
5906 return S->isUsesAllocatorsDecl(E->
getDecl())
5907 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5908 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5910 bool VisitStmt(
const Stmt *S) {
5911 for (
const Stmt *Child : S->
children()) {
5912 if (Child && Visit(Child))
5917 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5924 "Expected non-dependent context.");
5925 auto AllocateRange =
5928 auto PrivateRange = llvm::make_filter_range(Clauses, [](
const OMPClause *
C) {
5933 if (
Cl->getClauseKind() == OMPC_private) {
5935 I = PC->private_copies().begin();
5936 It = PC->varlist_begin();
5937 Et = PC->varlist_end();
5938 }
else if (
Cl->getClauseKind() == OMPC_firstprivate) {
5940 I = PC->private_copies().begin();
5941 It = PC->varlist_begin();
5942 Et = PC->varlist_end();
5943 }
else if (
Cl->getClauseKind() == OMPC_lastprivate) {
5945 I = PC->private_copies().begin();
5946 It = PC->varlist_begin();
5947 Et = PC->varlist_end();
5948 }
else if (
Cl->getClauseKind() == OMPC_linear) {
5950 I = PC->privates().begin();
5951 It = PC->varlist_begin();
5952 Et = PC->varlist_end();
5953 }
else if (
Cl->getClauseKind() == OMPC_reduction) {
5955 I = PC->privates().begin();
5956 It = PC->varlist_begin();
5957 Et = PC->varlist_end();
5958 }
else if (
Cl->getClauseKind() == OMPC_task_reduction) {
5960 I = PC->privates().begin();
5961 It = PC->varlist_begin();
5962 Et = PC->varlist_end();
5963 }
else if (
Cl->getClauseKind() == OMPC_in_reduction) {
5965 I = PC->privates().begin();
5966 It = PC->varlist_begin();
5967 Et = PC->varlist_end();
5969 llvm_unreachable(
"Expected private clause.");
5971 for (
Expr *E : llvm::make_range(It, Et)) {
5978 Expr *SimpleRefExpr = E;
5981 DeclToCopy.try_emplace(Res.first,
5989 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5991 AC->getAllocator()) {
5992 Expr *Allocator = AC->getAllocator();
5998 AllocatorChecker Checker(Stack);
5999 if (Checker.Visit(Allocator))
6001 diag::err_omp_allocator_not_in_uses_allocators)
6004 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
6010 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
6014 S.
Diag(AC->getAllocator()->getExprLoc(),
6015 diag::warn_omp_allocate_thread_on_task_target_directive)
6016 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
6018 for (
Expr *E : AC->varlist()) {
6021 Expr *SimpleRefExpr = E;
6026 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
6029 diag::err_omp_expected_private_copy_for_allocate);
6032 VarDecl *PrivateVD = DeclToCopy[VD];
6034 AllocatorKind, AC->getAllocator()))
6048class CaptureVars :
public TreeTransform<CaptureVars> {
6049 using BaseTransform = TreeTransform<CaptureVars>;
6052 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
6054 bool AlwaysRebuild() {
return true; }
6064 Ty =
C.getBitIntType(!
Signed, Bits);
6072 if (ILE->isTransparent())
6075 bool IsEmptyScalar = ILE->getNumInits() == 0 && Ty->
isScalarType();
6083 return Zero.isUsable() ?
Zero.get() : E;
6085 Expr *Syntactic = ILE->getSyntacticForm();
6086 if ((!IsEmptyScalar && !Ty->
isRecordType()) || !Syntactic)
6091 ILE->getRBraceLoc(),
true);
6104 BodyStmts.push_back(NewDeclStmt);
6142 DistParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
6153 auto BuildVarRef = [&](
VarDecl *VD) {
6158 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 0), LogicalTy, {});
6160 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
6166 Actions.
BuildBinOp(
nullptr, {}, BO_LT, BuildVarRef(NewStep),
Zero));
6170 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
6174 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
6178 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
6182 Actions.
BuildUnaryOp(
nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
6184 Actions.
BuildBinOp(
nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
6188 {}, {}, IsNegStep, BackwardDist, ForwardDist));
6190 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
6191 "Expected one of these relational operators");
6198 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
6202 if (Rel == BO_GE || Rel == BO_GT)
6204 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
6207 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
6213 if (Rel == BO_LE || Rel == BO_GE) {
6225 Expr *Divisor = BuildVarRef(NewStep);
6226 if (Rel == BO_GE || Rel == BO_GT)
6229 Expr *DivisorMinusOne =
6232 Actions.
BuildBinOp(
nullptr, {}, BO_Add, Range, DivisorMinusOne));
6234 Actions.
BuildBinOp(
nullptr, {}, BO_Div, RangeRoundUp, Divisor));
6244 Actions.
getCurScope(), {}, BO_Assign, DistRef, Dist));
6245 BodyStmts.push_back(ResultAssign);
6277 {
"Logical", LogicalTy},
6288 assert(!
Invalid &&
"Expecting capture-by-value to work.");
6297 TargetParam, LoopVarTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
6300 IndvarParam, LogicalTy,
VK_LValue, {},
nullptr,
nullptr, {},
nullptr);
6303 CaptureVars Recap(Actions);
6308 Actions.
BuildBinOp(
nullptr, {}, BO_Mul, NewStep, LogicalRef));
6323 BO_Assign, TargetRef, Advanced));
6336 if (
auto *For = dyn_cast<ForStmt>(AStmt)) {
6338 if (
auto *LCVarDeclStmt = dyn_cast<DeclStmt>(
Init)) {
6341 }
else if (
auto *LCAssign = dyn_cast<BinaryOperator>(
Init)) {
6343 assert(LCAssign->getOpcode() == BO_Assign &&
6344 "init part must be a loop variable assignment");
6348 llvm_unreachable(
"Cannot determine loop variable");
6351 Cond = For->getCond();
6352 Inc = For->getInc();
6353 }
else if (
auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
6354 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
6356 LUVDecl = RangeFor->getLoopVariable();
6358 Cond = RangeFor->getCond();
6359 Inc = RangeFor->getInc();
6361 llvm_unreachable(
"unhandled kind of loop");
6370 if (
auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
6371 LHS = CondBinExpr->getLHS();
6372 RHS = CondBinExpr->getRHS();
6373 CondRel = CondBinExpr->getOpcode();
6374 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
6375 assert(CondCXXOp->getNumArgs() == 2 &&
"Comparison should have 2 operands");
6376 LHS = CondCXXOp->getArg(0);
6377 RHS = CondCXXOp->getArg(1);
6378 switch (CondCXXOp->getOperator()) {
6379 case OO_ExclaimEqual:
6391 case OO_GreaterEqual:
6395 llvm_unreachable(
"unexpected iterator operator");
6398 llvm_unreachable(
"unexpected loop condition");
6403 std::swap(LHS, RHS);
6420 if (
auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
6422 switch (IncUn->getOpcode()) {
6432 llvm_unreachable(
"unhandled unary increment operator");
6436 llvm::APInt(Ctx.
getIntWidth(LogicalTy), Direction,
true),
6438 }
else if (
auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
6440 if (IncBin->getOpcode() == BO_AddAssign) {
6442 }
else if (IncBin->getOpcode() == BO_SubAssign) {
6445 llvm_unreachable(
"unhandled binary increment operator");
6446 }
else if (
auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
6447 switch (CondCXXOp->getOperator()) {
6450 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), 1), LogicalTy, {});
6454 Ctx, llvm::APInt(Ctx.
getIntWidth(LogicalTy), -1), LogicalTy, {});
6461 nullptr, {}, UO_Minus,
6465 llvm_unreachable(
"unhandled overloaded increment operator");
6468 llvm_unreachable(
"unknown increment expression");
6476 nullptr,
nullptr, {},
nullptr);
6477 return OMPCanonicalLoop::create(
getASTContext(), AStmt, DistanceFunc,
6478 LoopVarFunc, LVRef);
6490 "Loop transformation directive expected");
6491 return LoopTransform;
6498 Expr *UnresolvedMapper,
6510 for (
int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6511 auto *
C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6515 auto *MI =
C->mapperlist_begin();
6516 for (
auto I =
C->varlist_begin(), End =
C->varlist_end(); I != End;
6535 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6536 ElemType = ATy->getElementType();
6539 CanonType = ElemType;
6544 1, {CanonType,
nullptr});
6545 llvm::DenseMap<const Type *, Expr *> Visited;
6548 while (!Types.empty()) {
6551 std::tie(BaseType, CurFD) = Types.pop_back_val();
6552 while (ParentChain.back().second == 0)
6553 ParentChain.pop_back();
6554 --ParentChain.back().second;
6555 if (BaseType.isNull())
6558 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6561 auto It = Visited.find(BaseType.getTypePtr());
6562 if (It == Visited.end()) {
6570 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6574 It = Visited.try_emplace(BaseType.getTypePtr(), ER.
get()).first;
6581 Expr *BaseExpr = OE;
6582 for (
const auto &P : ParentChain) {
6600 SubExprs.push_back(BaseExpr);
6604 bool FirstIter =
true;
6614 ParentChain.emplace_back(CurFD, 1);
6616 ++ParentChain.back().second;
6618 Types.emplace_back(FieldTy, FD);
6622 if (SubExprs.empty())
6627 nullptr,
C->getMapTypeModifiers(),
C->getMapTypeModifiersLoc(),
6628 MapperIdScopeSpec, MapperId,
C->getMapType(),
6631 Clauses.push_back(NewClause);
6638class TeamsLoopChecker final :
public ConstStmtVisitor<TeamsLoopChecker> {
6645 void VisitOMPExecutableDirective(
const OMPExecutableDirective *D) {
6646 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6647 if (
const auto *
C = D->getSingleClause<OMPBindClause>())
6648 if (
C->getBindKind() == OMPC_BIND_parallel) {
6649 TeamsLoopCanBeParallelFor =
false;
6654 for (
const Stmt *Child : D->children())
6659 void VisitCallExpr(
const CallExpr *
C) {
6664 bool IsOpenMPAPI =
false;
6665 auto *FD = dyn_cast_or_null<FunctionDecl>(
C->getCalleeDecl());
6667 std::string Name = FD->getNameInfo().getAsString();
6668 IsOpenMPAPI = Name.find(
"omp_") == 0;
6670 TeamsLoopCanBeParallelFor =
6671 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6672 if (!TeamsLoopCanBeParallelFor)
6675 for (
const Stmt *Child :
C->children())
6680 void VisitCapturedStmt(
const CapturedStmt *S) {
6686 void VisitStmt(
const Stmt *S) {
6689 for (
const Stmt *Child : S->
children())
6693 explicit TeamsLoopChecker(Sema &SemaRef)
6694 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(
true) {}
6697 bool TeamsLoopCanBeParallelFor;
6702 TeamsLoopChecker Checker(SemaRef);
6703 Checker.Visit(AStmt);
6704 return Checker.teamsLoopCanBeParallelFor();
6718 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6719 BindKind = BC->getBindKind();
6731 BindKind = OMPC_BIND_thread;
6733 getLeafConstructsOrSelf(ParentDirective);
6735 if (ParentDirective == OMPD_unknown) {
6737 diag::err_omp_bind_required_on_loop);
6738 }
else if (ParentLeafs.back() == OMPD_parallel) {
6739 BindKind = OMPC_BIND_parallel;
6740 }
else if (ParentLeafs.back() == OMPD_teams) {
6741 BindKind = OMPC_BIND_teams;
6749 ClausesWithImplicit.push_back(
C);
6753 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6755 if (
C->getClauseKind() == OMPC_reduction)
6757 diag::err_omp_loop_reduction_clause);
6764 BindKind, StartLoc)) {
6771 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6774 bool ErrorFound =
false;
6775 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6777 if (AStmt && !
SemaRef.CurContext->isDependentContext() &&
6785 while (--ThisCaptureLevel >= 0)
6787 DSAChecker.Visit(S);
6795 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6797 DSAChecker.visitSubCaptures(CS);
6799 if (DSAChecker.isErrorFound())
6802 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6803 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6806 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6808 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6810 if (
auto *DMC = dyn_cast<OMPDefaultmapClause>(
C))
6811 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6812 PresentModifierLocs[DMC->getDefaultmapKind()] =
6813 DMC->getDefaultmapModifierLoc();
6817 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6819 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6820 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6824 if (
auto *IRC = dyn_cast<OMPInReductionClause>(
C)) {
6825 for (
Expr *E : IRC->taskgroup_descriptors())
6827 ImpInfo.Firstprivates.insert(E);
6832 if (
auto *DC = dyn_cast<OMPDetachClause>(
C))
6833 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6835 if (!ImpInfo.Firstprivates.empty()) {
6839 ClausesWithImplicit.push_back(
Implicit);
6841 ImpInfo.Firstprivates.size();
6846 if (!ImpInfo.Privates.empty()) {
6850 ClausesWithImplicit.push_back(
Implicit);
6852 ImpInfo.Privates.size();
6861 if (
getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6865 if (
auto *RC = dyn_cast<OMPReductionClause>(
C))
6866 for (
Expr *E : RC->varlist())
6868 ImplicitExprs.emplace_back(E);
6870 if (!ImplicitExprs.empty()) {
6876 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6879 ClausesWithImplicit.emplace_back(
Implicit);
6882 for (
unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6883 int ClauseKindCnt = -1;
6884 for (
unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6887 if (ImplicitMap.empty())
6893 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6894 MapperIdScopeSpec, MapperId, K,
true,
6897 ClausesWithImplicit.emplace_back(
Implicit);
6909 ClausesWithImplicit);
6919 VarsWithInheritedDSA);
6934 assert(ClausesWithImplicit.empty() &&
6935 "reverse directive does not support any clauses");
6942 case OMPD_interchange:
6956 VarsWithInheritedDSA);
6960 EndLoc, VarsWithInheritedDSA);
6967 assert(ClausesWithImplicit.empty() &&
6968 "No clauses are allowed for 'omp section' directive");
6976 assert(ClausesWithImplicit.empty() &&
6977 "No clauses are allowed for 'omp master' directive");
6988 case OMPD_parallel_for:
6990 EndLoc, VarsWithInheritedDSA);
6992 case OMPD_parallel_for_simd:
6994 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7000 case OMPD_parallel_master:
7004 case OMPD_parallel_masked:
7008 case OMPD_parallel_sections:
7016 case OMPD_taskyield:
7017 assert(ClausesWithImplicit.empty() &&
7018 "No clauses are allowed for 'omp taskyield' directive");
7019 assert(AStmt ==
nullptr &&
7020 "No associated statement allowed for 'omp taskyield' directive");
7024 assert(AStmt ==
nullptr &&
7025 "No associated statement allowed for 'omp error' directive");
7029 assert(ClausesWithImplicit.empty() &&
7030 "No clauses are allowed for 'omp barrier' directive");
7031 assert(AStmt ==
nullptr &&
7032 "No associated statement allowed for 'omp barrier' directive");
7036 assert(AStmt ==
nullptr &&
7037 "No associated statement allowed for 'omp taskwait' directive");
7040 case OMPD_taskgroup:
7045 assert(AStmt ==
nullptr &&
7046 "No associated statement allowed for 'omp flush' directive");
7050 assert(AStmt ==
nullptr &&
7051 "No associated statement allowed for 'omp depobj' directive");
7055 assert(AStmt ==
nullptr &&
7056 "No associated statement allowed for 'omp scan' directive");
7059 case OMPD_ordered_blockassoc:
7060 case OMPD_ordered_standalone:
7076 case OMPD_target_parallel:
7080 case OMPD_target_parallel_for:
7082 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7084 case OMPD_cancellation_point:
7085 assert(ClausesWithImplicit.empty() &&
7086 "No clauses are allowed for 'omp cancellation point' directive");
7087 assert(AStmt ==
nullptr &&
"No associated statement allowed for 'omp "
7088 "cancellation point' directive");
7092 assert(AStmt ==
nullptr &&
7093 "No associated statement allowed for 'omp cancel' directive");
7097 case OMPD_target_data:
7101 case OMPD_target_enter_data:
7105 case OMPD_target_exit_data:
7111 EndLoc, VarsWithInheritedDSA);
7113 case OMPD_taskloop_simd:
7115 EndLoc, VarsWithInheritedDSA);
7117 case OMPD_master_taskloop:
7119 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7121 case OMPD_masked_taskloop:
7123 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7125 case OMPD_master_taskloop_simd:
7127 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7129 case OMPD_masked_taskloop_simd:
7131 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7133 case OMPD_parallel_master_taskloop:
7135 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7137 case OMPD_parallel_masked_taskloop:
7139 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7141 case OMPD_parallel_master_taskloop_simd:
7143 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7145 case OMPD_parallel_masked_taskloop_simd:
7147 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7149 case OMPD_distribute:
7151 EndLoc, VarsWithInheritedDSA);
7153 case OMPD_target_update:
7157 case OMPD_distribute_parallel_for:
7159 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7161 case OMPD_distribute_parallel_for_simd:
7163 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7165 case OMPD_distribute_simd:
7167 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7169 case OMPD_target_parallel_for_simd:
7171 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7173 case OMPD_target_simd:
7175 EndLoc, VarsWithInheritedDSA);
7177 case OMPD_teams_distribute:
7179 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7181 case OMPD_teams_distribute_simd:
7183 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7185 case OMPD_teams_distribute_parallel_for_simd:
7187 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7189 case OMPD_teams_distribute_parallel_for:
7191 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7193 case OMPD_target_teams:
7197 case OMPD_target_teams_distribute:
7199 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7201 case OMPD_target_teams_distribute_parallel_for:
7203 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7205 case OMPD_target_teams_distribute_parallel_for_simd:
7207 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7209 case OMPD_target_teams_distribute_simd:
7211 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7214 assert(AStmt ==
nullptr &&
7215 "No associated statement allowed for 'omp interop' directive");
7224 EndLoc, VarsWithInheritedDSA);
7226 case OMPD_teams_loop:
7228 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7230 case OMPD_target_teams_loop:
7232 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7234 case OMPD_parallel_loop:
7236 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7238 case OMPD_target_parallel_loop:
7240 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7242 case OMPD_declare_target:
7243 case OMPD_end_declare_target:
7244 case OMPD_threadprivate:
7246 case OMPD_declare_reduction:
7247 case OMPD_declare_mapper:
7248 case OMPD_declare_simd:
7250 case OMPD_declare_variant:
7251 case OMPD_begin_declare_variant:
7252 case OMPD_end_declare_variant:
7253 llvm_unreachable(
"OpenMP Directive is not allowed");
7254 case OMPD_taskgraph:
7255 Diag(StartLoc, diag::err_omp_unexpected_directive)
7256 << 1 << getOpenMPDirectiveName(OMPD_taskgraph);
7260 llvm_unreachable(
"Unknown OpenMP directive");
7263 ErrorFound = Res.
isInvalid() || ErrorFound;
7267 if (
DSAStack->getDefaultDSA() == DSA_none ||
7268 DSAStack->getDefaultDSA() == DSA_private ||
7269 DSAStack->getDefaultDSA() == DSA_firstprivate) {
7272 switch (
C->getClauseKind()) {
7273 case OMPC_num_threads:
7274 case OMPC_dist_schedule:
7291 case OMPC_grainsize:
7292 case OMPC_num_tasks:
7295 case OMPC_novariants:
7296 case OMPC_nocontext:
7303 case OMPC_num_teams:
7304 case OMPC_thread_limit:
7312 case OMPC_proc_bind:
7314 case OMPC_firstprivate:
7315 case OMPC_lastprivate:
7317 case OMPC_reduction:
7318 case OMPC_task_reduction:
7319 case OMPC_in_reduction:
7323 case OMPC_copyprivate:
7326 case OMPC_mergeable:
7343 case OMPC_defaultmap:
7346 case OMPC_use_device_ptr:
7347 case OMPC_use_device_addr:
7348 case OMPC_is_device_ptr:
7349 case OMPC_has_device_addr:
7350 case OMPC_nontemporal:
7353 case OMPC_inclusive:
7354 case OMPC_exclusive:
7355 case OMPC_uses_allocators:
7362 case OMPC_allocator:
7365 case OMPC_threadprivate:
7366 case OMPC_groupprivate:
7369 case OMPC_unified_address:
7370 case OMPC_unified_shared_memory:
7371 case OMPC_reverse_offload:
7372 case OMPC_dynamic_allocators:
7373 case OMPC_atomic_default_mem_order:
7374 case OMPC_self_maps:
7375 case OMPC_device_type:
7380 llvm_unreachable(
"Unexpected clause");
7382 for (
Stmt *CC :
C->children()) {
7384 DSAChecker.Visit(CC);
7387 for (
const auto &P : DSAChecker.getVarsWithInheritedDSA())
7388 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
7390 for (
const auto &P : VarsWithInheritedDSA) {
7394 if (
DSAStack->getDefaultDSA() == DSA_none ||
7395 DSAStack->getDefaultDSA() == DSA_private ||
7396 DSAStack->getDefaultDSA() == DSA_firstprivate) {
7397 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
7398 << P.first << P.second->getSourceRange();
7399 Diag(
DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
7401 Diag(P.second->getExprLoc(),
7402 diag::err_omp_defaultmap_no_attr_for_variable)
7403 << P.first << P.second->getSourceRange();
7405 diag::note_omp_defaultmap_attr_none);
7411 if (isAllowedClauseForDirective(D, OMPC_if,
7413 AllowedNameModifiers.push_back(D);
7415 if (!AllowedNameModifiers.empty())
7422 if (!
SemaRef.CurContext->isDependentContext() &&
7424 !(
DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
7425 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
7426 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
7427 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
7429 DSAStack->addTargetDirLocation(StartLoc);
7440 assert(Aligneds.size() == Alignments.size());
7441 assert(Linears.size() == LinModifiers.size());
7442 assert(Linears.size() == Steps.size());
7446 const int SimdId = 0;
7448 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7453 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7454 ADecl = FTD->getTemplatedDecl();
7456 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7458 Diag(ADecl->
getLocation(), diag::err_omp_function_expected) << SimdId;
7474 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7475 const Expr *UniformedLinearThis =
nullptr;
7476 for (
const Expr *E : Uniforms) {
7478 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7479 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->
getDecl()))
7480 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7481 FD->getParamDecl(PVD->getFunctionScopeIndex())
7483 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7487 UniformedLinearThis = E;
7501 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7502 const Expr *AlignedThis =
nullptr;
7503 for (
const Expr *E : Aligneds) {
7505 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7506 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->
getDecl())) {
7508 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7509 FD->getParamDecl(PVD->getFunctionScopeIndex())
7513 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
7518 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7523 .getNonReferenceType()
7524 .getUnqualifiedType()
7525 .getCanonicalType();
7528 Diag(E->
getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7530 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7554 for (
Expr *E : Alignments) {
7558 NewAligns.push_back(Align.
get());
7569 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7570 const bool IsUniformedThis = UniformedLinearThis !=
nullptr;
7571 auto MI = LinModifiers.begin();
7572 for (
const Expr *E : Linears) {
7576 if (
const auto *DRE = dyn_cast<DeclRefExpr>(E))
7577 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->
getDecl())) {
7579 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7580 FD->getParamDecl(PVD->getFunctionScopeIndex())
7584 if (
auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7589 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7594 if (
auto It = UniformedArgs.find(CanonPVD);
7595 It != UniformedArgs.end()) {
7600 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7604 LinearArgs[CanonPVD] = E;
7610 PVD->getOriginalType(),
7616 if (UniformedLinearThis) {
7622 Diag(UniformedLinearThis->
getExprLoc(), diag::note_omp_explicit_dsa)
7627 UniformedLinearThis = E;
7638 Expr *Step =
nullptr;
7639 Expr *NewStep =
nullptr;
7641 for (
Expr *E : Steps) {
7643 if (Step == E || !E) {
7644 NewSteps.push_back(E ? NewStep :
nullptr);
7648 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7649 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->
getDecl())) {
7651 if (UniformedArgs.count(CanonPVD) == 0) {
7658 NewSteps.push_back(Step);
7673 .VerifyIntegerConstantExpression(
7677 NewSteps.push_back(NewStep);
7679 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7681 Uniforms.size(),
const_cast<Expr **
>(Aligneds.data()), Aligneds.size(),
7682 const_cast<Expr **
>(NewAligns.data()), NewAligns.size(),
7683 const_cast<Expr **
>(Linears.data()), Linears.size(),
7684 const_cast<unsigned *
>(LinModifiers.data()), LinModifiers.size(),
7685 NewSteps.data(), NewSteps.size(), SR);
7695 "Unexpected directive category");
7704 llvm_unreachable(
"Unknown OpenMP directive");
7713 "Expected function type with prototype.");
7715 "Expected function with type with no prototype.");
7717 "Expected function with prototype.");
7725 Param->setScopeInfo(0, Params.size());
7726 Param->setImplicit();
7727 Params.push_back(Param);
7730 FD->setParams(Params);
7737 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7738 FD = UTemplDecl->getTemplatedDecl();
7741 assert(FD &&
"Expected a function declaration!");
7746 if (!
SemaRef.inTemplateInstantiation()) {
7747 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7750 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7754SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(
OMPTraitInfo &TI)
7755 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7763 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7766 bool IsTemplated = !TemplateParamLists.empty();
7769 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7786 for (
auto *Candidate : Lookup) {
7787 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7792 if (
SemaRef.Context.isSameTemplateParameterList(
7793 FTD->getTemplateParameters(), TemplateParamLists.back()))
7794 UDecl = FTD->getTemplatedDecl();
7795 }
else if (!IsTemplated)
7796 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7810 FType, UDeclTy,
false,
7817 Bases.push_back(UDecl);
7821 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7823 if (Bases.empty() && UseImplicitBase) {
7825 Decl *BaseD =
SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7827 if (
auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7828 Bases.push_back(BaseTemplD->getTemplatedDecl());
7833 std::string MangledName;
7836 MangledName += DVScope.NameSuffix;
7851 if (
auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7852 FD = UTemplDecl->getTemplatedDecl();
7860 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7861 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7866 BaseFD->addAttr(OMPDeclareVariantA);
7884 if (!CalleeFnDecl) {
7889 if ((DRE = dyn_cast<DeclRefExpr>(E)))
7891 if (
auto *ME = dyn_cast<MemberExpr>(E))
7893 else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
7899 if (VD && !VD->
hasAttr<OMPTargetIndirectCallAttr>()) {
7902 ML->DeclarationMarkedOpenMPIndirectCall(VD);
7911 CalleeFnDecl->
getName().starts_with_insensitive(
"omp_")) {
7914 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7917 if (!CalleeFnDecl->
hasAttr<OMPDeclareVariantAttr>())
7922 CE](StringRef ISATrait) {
7936 while (CalleeFnDecl) {
7937 for (OMPDeclareVariantAttr *A :
7939 Expr *VariantRef = A->getVariantFuncRef();
7941 VariantMatchInfo VMI;
7944 if (!isVariantApplicableInContext(VMI, OMPCtx,
7948 VMIs.push_back(VMI);
7949 Exprs.push_back(VariantRef);
7957 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7977 if (
auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7978 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7980 Context, MemberCall->getImplicitObjectArgument(),
7981 false, SpecializedMethod, Context.BoundMemberTy,
7982 MemberCall->getValueKind(), MemberCall->getObjectKind());
7984 NewCall =
SemaRef.BuildCallExpr(
Scope, BestExpr, LParenLoc, ArgExprs,
7985 RParenLoc, ExecConfig);
7987 if (
CallExpr *NCE = dyn_cast<CallExpr>(NewCall.
get())) {
7988 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7990 CalleeFnType, NewCalleeFnDecl->
getType(),
8001 VMIs.erase(VMIs.begin() + BestIdx);
8002 Exprs.erase(Exprs.begin() + BestIdx);
8003 }
while (!VMIs.empty());
8010std::optional<std::pair<FunctionDecl *, Expr *>>
8014 unsigned NumAppendArgs,
8018 return std::nullopt;
8020 const int VariantId = 1;
8023 Diag(SR.
getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
8025 return std::nullopt;
8028 if (
auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
8029 ADecl = FTD->getTemplatedDecl();
8032 auto *FD = dyn_cast<FunctionDecl>(ADecl);
8036 return std::nullopt;
8039 auto &&HasMultiVersionAttributes = [](
const FunctionDecl *FD) {
8042 return FD->isMultiVersion() || FD->
hasAttr<TargetAttr>();
8045 if (HasMultiVersionAttributes(FD)) {
8046 Diag(FD->
getLocation(), diag::err_omp_declare_variant_incompat_attributes)
8048 return std::nullopt;
8053 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_used)
8058 if (!FD->isThisDeclarationADefinition() && FD->isDefined(
Definition) &&
8060 Diag(SR.
getBegin(), diag::warn_omp_declare_variant_after_emitted)
8065 Diag(SR.
getBegin(), diag::err_omp_function_expected) << VariantId;
8066 return std::nullopt;
8069 auto ShouldDelayChecks = [](
Expr *&E, bool) {
8075 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef,
false) ||
8077 return std::make_pair(FD, VariantRef);
8080 auto HandleNonConstantScoresAndConditions = [
this](
Expr *&E,
8081 bool IsScore) ->
bool {
8087 Diag(E->
getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
8095 diag::err_omp_declare_variant_user_condition_not_constant)
8101 return std::nullopt;
8104 if (NumAppendArgs) {
8107 Diag(FD->
getLocation(), diag::err_omp_declare_variant_prototype_required)
8109 return std::nullopt;
8118 TD = dyn_cast_or_null<TypeDecl>(ND);
8121 Diag(SR.
getBegin(), diag::err_omp_interop_type_not_found) << SR;
8122 return std::nullopt;
8127 if (PTy->isVariadic()) {
8128 Diag(FD->
getLocation(), diag::err_omp_append_args_with_varargs) << SR;
8129 return std::nullopt;
8132 Params.append(PTy->param_type_begin(), PTy->param_type_end());
8133 Params.insert(Params.end(), NumAppendArgs, InteropType);
8134 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
8135 PTy->getExtProtoInfo());
8143 auto *
Method = dyn_cast<CXXMethodDecl>(FD);
8145 FnPtrType = Context.getMemberPointerType(
8146 AdjustedFnType, std::nullopt,
Method->getParent());
8158 return std::nullopt;
8160 VariantRef = ER.
get();
8162 FnPtrType = Context.getPointerType(AdjustedFnType);
8164 QualType VarianPtrType = Context.getPointerType(VariantRef->
getType());
8168 false, Sema::AllowedExplicit::None,
8174 diag::err_omp_declare_variant_incompat_types)
8178 return std::nullopt;
8180 VariantRefCast =
SemaRef.PerformImplicitConversion(
8184 return std::nullopt;
8188 Expr *PossibleAddrOfVariantRef = VariantRefCast.
get();
8189 if (
auto *UO = dyn_cast<UnaryOperator>(
8191 VariantRefCast = UO->getSubExpr();
8200 return std::nullopt;
8208 return std::nullopt;
8210 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->
getDecl());
8214 return std::nullopt;
8219 diag::err_omp_declare_variant_same_base_function)
8221 return std::nullopt;
8227 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
8230 diag::err_omp_declare_variant_incompat_types)
8231 << NewFD->getType() << FD->
getType() << (NumAppendArgs ? 1 : 0)
8233 return std::nullopt;
8238 else if (NewFD->getType()->isFunctionNoProtoType())
8244 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
8246 diag::warn_omp_declare_variant_marked_as_declare_variant)
8249 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->
getRange();
8250 Diag(SR.
getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
8251 return std::nullopt;
8254 enum DoesntSupport {
8263 if (
const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
8264 if (CXXFD->isVirtual()) {
8267 return std::nullopt;
8273 return std::nullopt;
8279 return std::nullopt;
8283 if (FD->isDeleted()) {
8286 return std::nullopt;
8289 if (FD->isDefaulted()) {
8292 return std::nullopt;
8295 if (FD->isConstexpr()) {
8297 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
8298 return std::nullopt;
8302 if (
SemaRef.areMultiversionVariantFunctionsCompatible(
8308 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
8310 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
8314 return std::nullopt;
8324 auto isDependent = [](
const Expr *E) {
8332 assert(Info.
HasPreferAttrs &&
"null Fr requires OMP 6.0 syntax");
8333 }
else if (!isDependent(E)) {
8343 const auto *SL = dyn_cast<StringLiteral>(A);
8348 StringRef Str = SL->getString();
8349 if (!Str.starts_with(
"ompx_")) {
8350 S.
Diag(A->
getExprLoc(), diag::err_omp_interop_attr_missing_ompx_prefix)
8354 if (Str.contains(
',')) {
8355 S.
Diag(A->
getExprLoc(), diag::err_omp_interop_attr_contains_comma)
8369 bool StrictlyPositive,
8375 if (StrictlyPositive ? !
Result.isStrictlyPositive() :
Result.isNegative()) {
8376 S.
Diag(E->
getExprLoc(), diag::err_omp_negative_expression_in_clause)
8381 if (!
Result.isRepresentableByInt64()) {
8382 S.
Diag(E->
getExprLoc(), diag::err_omp_large_expression_in_clause)
8403 Bound.
E &&
"expected an adjust_args bound expression");
8413 "expected an adjust_args range");
8436 AdjustOp != OMPC_ADJUST_ARGS_need_device_ptr) {
8437 Diag(Loc, diag::err_omp_unexpected_clause_modifier)
8438 << getOpenMPClauseName(OMPC_adjust_args);
8442 NeedDevicePtrModifier, Items);
8456 if (!AdjustArgs.empty() || !AppendArgs.empty()) {
8457 VariantMatchInfo VMI;
8459 if (!llvm::is_contained(
8460 VMI.ConstructTraits,
8461 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
8462 if (!AdjustArgs.empty())
8463 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
8465 if (!AppendArgs.empty())
8466 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
8476 llvm::SmallSet<uint64_t, 4> AdjustPositions;
8486 for (
unsigned Pos : Positions) {
8487 if (!AdjustPositions.insert(Pos).second) {
8489 diag::err_omp_adjust_arg_multiple_clauses)
8498 assert(ItemInfo.E &&
"expected an adjust_args expression");
8502 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Item)) {
8503 if (
const auto *PVD = dyn_cast<ParmVarDecl>(DRE->
getDecl())) {
8505 if (FD->
getNumParams() > PVD->getFunctionScopeIndex() &&
8508 if (!AdjustVars.insert(CanonPVD).second) {
8510 diag::err_omp_adjust_arg_multiple_clauses)
8538 if (!AdjustPositions.insert(Pos.getZExtValue()).second) {
8539 Diag(Item->
getExprLoc(), diag::err_omp_adjust_arg_multiple_clauses)
8555 Diag(Item->
getExprLoc(), diag::err_omp_adjust_args_invalid_item);
8569 if (Desc->AdjustOp != OMPC_ADJUST_ARGS_need_device_addr)
8579 for (
unsigned Pos : Positions) {
8586 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
8600 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
8603 AdjustArgs.size(),
const_cast<OMPInteropInfo *
>(AppendArgs.data()),
8604 AppendArgs.size(), SR);
8610 auto *CS = dyn_cast<CapturedStmt>(AStmt);
8611 assert(CS &&
"Captured statement expected");
8620 ThisCaptureLevel > 1; --ThisCaptureLevel) {
8647 return OMPParallelDirective::Create(
8654struct LoopIterationSpace final {
8657 bool IsStrictCompare =
false;
8659 Expr *PreCond =
nullptr;
8662 Expr *NumIterations =
nullptr;
8664 Expr *CounterVar =
nullptr;
8666 Expr *PrivateCounterVar =
nullptr;
8668 Expr *CounterInit =
nullptr;
8671 Expr *CounterStep =
nullptr;
8673 bool Subtract =
false;
8683 Expr *MinValue =
nullptr;
8687 Expr *MaxValue =
nullptr;
8689 bool IsNonRectangularLB =
false;
8691 bool IsNonRectangularUB =
false;
8694 unsigned LoopDependentIdx = 0;
8698 Expr *FinalCondition =
nullptr;
8705 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8706 VarDecl *ForbiddenVar =
nullptr;
8710 explicit ForSubExprChecker(
8711 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
8712 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
8715 ShouldVisitImplicitCode =
true;
8718 bool VisitDeclRefExpr(DeclRefExpr *E)
override {
8723 if (
V->getType()->isReferenceType()) {
8724 VarDecl *VD =
V->getDefinition();
8727 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
8733 Decl *Canon =
V->getCanonicalDecl();
8734 if (CollapsedLoopVarDecls.contains(Canon)) {
8743 VarDecl *getForbiddenVar()
const {
return ForbiddenVar; }
8744 SourceRange getErrRange()
const {
return ErrLoc; }
8750class OpenMPIterationSpaceChecker {
8754 bool SupportsNonRectangular;
8758 SourceLocation DefaultLoc;
8760 SourceLocation ConditionLoc;
8762 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8764 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars;
8766 SourceRange InitSrcRange;
8768 SourceRange ConditionSrcRange;
8770 SourceRange IncrementSrcRange;
8772 ValueDecl *LCDecl =
nullptr;
8774 Expr *LCRef =
nullptr;
8780 Expr *Step =
nullptr;
8787 std::optional<bool> TestIsLessOp;
8789 bool TestIsStrictOp =
false;
8791 bool SubtractStep =
false;
8793 const ValueDecl *DepDecl =
nullptr;
8796 std::optional<unsigned> InitDependOnLC;
8799 std::optional<unsigned> CondDependOnLC;
8801 std::optional<unsigned> doesDependOnLoopCounter(
const Stmt *S,
8802 bool IsInitializer);
8808 OpenMPIterationSpaceChecker(
8809 Sema &SemaRef,
bool SupportsNonRectangular, DSAStackTy &Stack,
8810 SourceLocation DefaultLoc,
8811 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls,
8812 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars)
8813 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8814 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8815 CollapsedLoopVarDecls(CollapsedLoopDecls),
8816 CollapsedLoopInductionVars(CollapsedLoopInductionVars) {}
8819 bool checkAndSetInit(Stmt *S,
bool EmitDiags =
true);
8822 bool checkAndSetCond(Expr *S);
8825 bool checkAndSetInc(Expr *S);
8827 ValueDecl *getLoopDecl()
const {
return LCDecl; }
8829 Expr *getLoopDeclRefExpr()
const {
return LCRef; }
8831 SourceRange getInitSrcRange()
const {
return InitSrcRange; }
8833 SourceRange getConditionSrcRange()
const {
return ConditionSrcRange; }
8835 SourceRange getIncrementSrcRange()
const {
return IncrementSrcRange; }
8837 bool shouldSubtractStep()
const {
return SubtractStep; }
8839 bool isStrictTestOp()
const {
return TestIsStrictOp; }
8841 Expr *buildNumIterations(
8842 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces,
bool LimitedType,
8843 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8846 buildPreCond(Scope *S, Expr *Cond,
8847 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8850 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8851 DSAStackTy &DSA)
const;
8854 Expr *buildPrivateCounterVar()
const;
8858 Expr *buildCounterStep()
const;
8862 buildOrderedLoopData(Scope *S, Expr *Counter,
8863 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8864 SourceLocation Loc, Expr *Inc =
nullptr,
8867 std::pair<Expr *, Expr *> buildMinMaxValues(
8868 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const;
8870 Expr *buildFinalCondition(Scope *S)
const;
8872 bool dependent()
const;
8874 bool doesInitDependOnLC()
const {
return InitDependOnLC.has_value(); }
8876 bool doesCondDependOnLC()
const {
return CondDependOnLC.has_value(); }
8878 unsigned getLoopDependentIdx()
const {
8879 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8885 bool checkAndSetIncRHS(Expr *RHS);
8887 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8890 bool setUB(Expr *NewUB, std::optional<bool> LessOp,
bool StrictOp,
8891 SourceRange SR, SourceLocation SL);
8893 bool setStep(Expr *NewStep,
bool Subtract);
8895 bool checkNonRectangularBound(
const Expr *E,
bool IsInitializer)
const;
8898bool OpenMPIterationSpaceChecker::dependent()
const {
8900 assert(!LB && !UB && !Step);
8911 while (!Worklist.empty()) {
8912 const Stmt *S = Worklist.pop_back_val();
8915 if (
const auto *SE = dyn_cast<StmtExpr>(S))
8917 llvm::append_range(Worklist, S->
children());
8922bool OpenMPIterationSpaceChecker::checkNonRectangularBound(
8923 const Expr *E,
bool IsInitializer)
const {
8925 const StmtExpr *SE = findStmtExpr(E);
8929 diag::err_omp_stmt_expr_in_non_rectangular_loop)
8930 << (IsInitializer ? 0 : 1);
8934bool OpenMPIterationSpaceChecker::setLCDeclAndLB(
ValueDecl *NewLCDecl,
8936 Expr *NewLB,
bool EmitDiags) {
8938 assert(LCDecl ==
nullptr && LB ==
nullptr && LCRef ==
nullptr &&
8939 UB ==
nullptr && Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8944 LCRef = NewLCRefExpr;
8945 if (
auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8947 if ((Ctor->isCopyOrMoveConstructor() ||
8948 Ctor->isConvertingConstructor(
false)) &&
8949 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
8953 InitDependOnLC = doesDependOnLoopCounter(LB,
true);
8954 if (InitDependOnLC && checkNonRectangularBound(LB,
true))
8960bool OpenMPIterationSpaceChecker::setUB(
Expr *NewUB, std::optional<bool> LessOp,
8964 assert(LCDecl !=
nullptr && LB !=
nullptr && UB ==
nullptr &&
8965 Step ==
nullptr && !TestIsLessOp && !TestIsStrictOp);
8970 TestIsLessOp = LessOp;
8971 TestIsStrictOp = StrictOp;
8972 ConditionSrcRange = SR;
8974 CondDependOnLC = doesDependOnLoopCounter(UB,
false);
8976 if ((InitDependOnLC || CondDependOnLC) &&
8977 checkNonRectangularBound(UB,
false))
8982bool OpenMPIterationSpaceChecker::setStep(
Expr *NewStep,
bool Subtract) {
8984 assert(LCDecl !=
nullptr && LB !=
nullptr && Step ==
nullptr);
8995 NewStep = Val.
get();
9008 std::optional<llvm::APSInt>
Result =
9019 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
9020 if (UB && (IsConstZero ||
9021 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
9022 : (IsConstPos || (IsUnsigned && !Subtract))))) {
9024 diag::err_omp_loop_incr_not_compatible)
9026 SemaRef.
Diag(ConditionLoc,
9027 diag::note_omp_loop_cond_requires_compatible_incr)
9028 << *TestIsLessOp << ConditionSrcRange;
9031 if (*TestIsLessOp == Subtract) {
9035 Subtract = !Subtract;
9040 SubtractStep = Subtract;
9047class LoopCounterRefChecker final
9051 const ValueDecl *CurLCDecl =
nullptr;
9052 const ValueDecl *DepDecl =
nullptr;
9053 const ValueDecl *PrevDepDecl =
nullptr;
9054 bool IsInitializer =
true;
9055 bool SupportsNonRectangular;
9056 unsigned BaseLoopId = 0;
9057 bool checkDecl(
const Expr *E,
const ValueDecl *VD) {
9059 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
9060 << (IsInitializer ? 0 : 1);
9063 const auto &&
Data = Stack.isLoopControlVariable(VD);
9068 SmallString<128> Name;
9069 llvm::raw_svector_ostream
OS(Name);
9073 diag::err_omp_wrong_dependency_iterator_type)
9075 SemaRef.Diag(VD->
getLocation(), diag::note_previous_decl) << VD;
9078 if (
Data.first && !SupportsNonRectangular) {
9079 SemaRef.Diag(E->
getExprLoc(), diag::err_omp_invariant_dependency);
9083 (DepDecl || (PrevDepDecl &&
9085 if (!DepDecl && PrevDepDecl)
9086 DepDecl = PrevDepDecl;
9087 SmallString<128> Name;
9088 llvm::raw_svector_ostream
OS(Name);
9092 diag::err_omp_invariant_or_linear_dependency)
9098 BaseLoopId =
Data.first;
9104 bool VisitDeclRefExpr(
const DeclRefExpr *E) {
9105 const ValueDecl *VD = E->
getDecl();
9107 return checkDecl(E, VD);
9110 bool VisitMemberExpr(
const MemberExpr *E) {
9114 return checkDecl(E, VD);
9118 bool VisitStmt(
const Stmt *S) {
9120 for (
const Stmt *Child : S->
children())
9121 Res = (Child && Visit(Child)) || Res;
9124 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
9125 const ValueDecl *CurLCDecl,
bool IsInitializer,
9126 const ValueDecl *PrevDepDecl =
nullptr,
9127 bool SupportsNonRectangular =
true)
9128 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
9129 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
9130 SupportsNonRectangular(SupportsNonRectangular) {}
9131 unsigned getBaseLoopId()
const {
9132 assert(CurLCDecl &&
"Expected loop dependency.");
9135 const ValueDecl *getDepDecl()
const {
9136 assert(CurLCDecl &&
"Expected loop dependency.");
9142std::optional<unsigned>
9143OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
const Stmt *S,
9144 bool IsInitializer) {
9146 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
9147 DepDecl, SupportsNonRectangular);
9148 if (LoopStmtChecker.Visit(S)) {
9149 DepDecl = LoopStmtChecker.getDepDecl();
9150 return LoopStmtChecker.getBaseLoopId();
9152 return std::nullopt;
9155bool OpenMPIterationSpaceChecker::checkAndSetInit(
Stmt *S,
bool EmitDiags) {
9166 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
9170 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
9171 if (!ExprTemp->cleanupsHaveSideEffects())
9172 S = ExprTemp->getSubExpr();
9174 if (!CollapsedLoopVarDecls.empty()) {
9175 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
9176 if (!FSEC.TraverseStmt(S)) {
9178 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
9179 <<
Range.getEnd() << 0 << FSEC.getForbiddenVar();
9187 auto CheckBindingAsLoopVar = [&](
ValueDecl *LoopVar,
9192 SemaRef.Diag(Loc, diag::err_omp_loop_var_is_structured_binding)
9202 SemaRef.Diag(Loc, diag::err_omp_loop_var_reused_in_collapsed_loop)
9210 if (
Expr *E = dyn_cast<Expr>(S))
9212 if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
9213 if (BO->getOpcode() == BO_Assign) {
9215 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
9216 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
9219 ValueDecl *LoopVar = ME->getMemberDecl();
9220 if (CheckLoopVarReuse(LoopVar, DRE->
getLocation()))
9222 return setLCDeclAndLB(LoopVar, ME, BO->getRHS(), EmitDiags);
9225 if (CheckBindingAsLoopVar(LoopVar, DRE->
getLocation()))
9227 if (CheckLoopVarReuse(LoopVar, DRE->
getLocation()))
9229 return setLCDeclAndLB(LoopVar, DRE, BO->getRHS(), EmitDiags);
9231 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
9232 if (ME->isArrow() &&
9234 ValueDecl *LoopVar = ME->getMemberDecl();
9235 if (CheckLoopVarReuse(LoopVar, LHS->
getBeginLoc()))
9237 return setLCDeclAndLB(LoopVar, ME, BO->getRHS(), EmitDiags);
9241 }
else if (
auto *DS = dyn_cast<DeclStmt>(S)) {
9242 if (DS->isSingleDecl()) {
9243 if (
auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
9244 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
9248 diag::ext_omp_loop_not_canonical_init)
9250 if (CheckLoopVarReuse(Var, Var->getLocation()))
9252 return setLCDeclAndLB(
9255 Var->getType().getNonReferenceType(),
9257 Var->getInit(), EmitDiags);
9261 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
9262 if (CE->getOperator() == OO_Equal) {
9263 Expr *LHS = CE->getArg(0);
9264 if (
auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
9265 if (
auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->
getDecl()))
9268 ValueDecl *LoopVar = ME->getMemberDecl();
9269 if (CheckLoopVarReuse(LoopVar, DRE->
getLocation()))
9271 return setLCDeclAndLB(LoopVar, ME, CE->getArg(1), EmitDiags);
9274 if (CheckBindingAsLoopVar(LoopVar, DRE->
getLocation()))
9276 if (CheckLoopVarReuse(LoopVar, DRE->
getLocation()))
9278 return setLCDeclAndLB(LoopVar, DRE, CE->getArg(1), EmitDiags);
9280 if (
auto *ME = dyn_cast<MemberExpr>(LHS)) {
9281 if (ME->isArrow() &&
9283 ValueDecl *LoopVar = ME->getMemberDecl();
9284 if (CheckLoopVarReuse(LoopVar, LHS->
getBeginLoc()))
9286 return setLCDeclAndLB(LoopVar, ME, CE->getArg(1), EmitDiags);
9292 if (dependent() || SemaRef.CurContext->isDependentContext())
9295 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_init)
9307 if (
const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
9309 if ((Ctor->isCopyOrMoveConstructor() ||
9310 Ctor->isConvertingConstructor(
false)) &&
9311 CE->getNumArgs() > 0 && CE->getArg(0) !=
nullptr)
9313 if (
const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
9314 if (
const auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
9317 if (
const auto *ME = dyn_cast_or_null<MemberExpr>(E))
9318 if (ME->isArrow() &&
isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
9323bool OpenMPIterationSpaceChecker::checkAndSetCond(
Expr *S) {
9330 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
9332 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
9333 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
9339 if (!CollapsedLoopVarDecls.empty()) {
9340 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
9341 if (!FSEC.TraverseStmt(S)) {
9343 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
9344 <<
Range.getEnd() << 1 << FSEC.getForbiddenVar();
9350 auto &&CheckAndSetCond =
9355 if (getInitLCDecl(LHS) == LCDecl)
9356 return setUB(
const_cast<Expr *
>(RHS),
9357 (Opcode == BO_LT || Opcode == BO_LE),
9358 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
9359 if (getInitLCDecl(RHS) == LCDecl)
9360 return setUB(
const_cast<Expr *
>(LHS),
9361 (Opcode == BO_GT || Opcode == BO_GE),
9362 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
9363 }
else if (IneqCondIsCanonical && Opcode == BO_NE) {
9364 return setUB(
const_cast<Expr *
>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
9368 return std::nullopt;
9370 std::optional<bool> Res;
9371 if (
auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
9374 RBO->getOperatorLoc());
9375 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
9376 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
9377 BO->getSourceRange(), BO->getOperatorLoc());
9378 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
9379 if (CE->getNumArgs() == 2) {
9380 Res = CheckAndSetCond(
9382 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
9387 if (dependent() || SemaRef.CurContext->isDependentContext())
9389 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
9390 << (IneqCondIsCanonical ? 1 : 0) << S->
getSourceRange() << LCDecl;
9394bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(
Expr *RHS) {
9401 if (
auto *BO = dyn_cast<BinaryOperator>(RHS)) {
9402 if (BO->isAdditiveOp()) {
9403 bool IsAdd = BO->getOpcode() == BO_Add;
9404 if (getInitLCDecl(BO->getLHS()) == LCDecl)
9405 return setStep(BO->getRHS(), !IsAdd);
9406 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
9407 return setStep(BO->getLHS(),
false);
9409 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
9410 bool IsAdd = CE->getOperator() == OO_Plus;
9411 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
9412 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
9413 return setStep(CE->getArg(1), !IsAdd);
9414 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
9415 return setStep(CE->getArg(0),
false);
9418 if (dependent() || SemaRef.CurContext->isDependentContext())
9420 SemaRef.Diag(RHS->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
9425bool OpenMPIterationSpaceChecker::checkAndSetInc(
Expr *S) {
9440 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
9443 if (
auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
9444 if (!ExprTemp->cleanupsHaveSideEffects())
9445 S = ExprTemp->getSubExpr();
9447 if (!CollapsedLoopVarDecls.empty()) {
9448 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
9449 if (!FSEC.TraverseStmt(S)) {
9451 SemaRef.Diag(
Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
9452 <<
Range.getEnd() << 2 << FSEC.getForbiddenVar();
9459 if (
auto *UO = dyn_cast<UnaryOperator>(S)) {
9460 if (UO->isIncrementDecrementOp() &&
9461 getInitLCDecl(UO->getSubExpr()) == LCDecl)
9462 return setStep(SemaRef
9463 .ActOnIntegerConstant(UO->getBeginLoc(),
9464 (UO->isDecrementOp() ? -1 : 1))
9467 }
else if (
auto *BO = dyn_cast<BinaryOperator>(S)) {
9468 switch (BO->getOpcode()) {
9471 if (getInitLCDecl(BO->getLHS()) == LCDecl)
9472 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
9475 if (getInitLCDecl(BO->getLHS()) == LCDecl)
9476 return checkAndSetIncRHS(BO->getRHS());
9481 }
else if (
auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
9482 switch (CE->getOperator()) {
9485 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
9486 return setStep(SemaRef
9487 .ActOnIntegerConstant(
9489 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
9495 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
9496 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
9499 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
9500 return checkAndSetIncRHS(CE->getArg(1));
9506 if (dependent() || SemaRef.CurContext->isDependentContext())
9508 SemaRef.Diag(S->
getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
9515 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9516 StringRef Name =
".capture_expr.") {
9527 auto I = Captures.find(
Capture);
9528 if (I != Captures.end())
9541 bool TestIsStrictOp,
bool RoundToStep,
9542 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9543 std::optional<unsigned> InitDependOnLC,
9544 std::optional<unsigned> CondDependOnLC) {
9545 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
9548 llvm::APSInt LRes, SRes;
9549 bool IsLowerConst =
false, IsStepConst =
false;
9550 if (std::optional<llvm::APSInt> Res =
9553 IsLowerConst =
true;
9555 if (std::optional<llvm::APSInt> Res =
9560 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
9561 ((!TestIsStrictOp && LRes.isNonNegative()) ||
9562 (TestIsStrictOp && LRes.isStrictlyPositive()));
9563 bool NeedToReorganize =
false;
9565 if (!NoNeedToConvert && IsLowerConst &&
9566 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
9567 NoNeedToConvert =
true;
9569 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
9570 ? LRes.getBitWidth()
9571 : SRes.getBitWidth();
9572 LRes = LRes.extend(BW + 1);
9573 LRes.setIsSigned(
true);
9574 SRes = SRes.extend(BW + 1);
9575 SRes.setIsSigned(
true);
9577 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
9578 LRes = LRes.trunc(BW);
9580 if (TestIsStrictOp) {
9581 unsigned BW = LRes.getBitWidth();
9582 LRes = LRes.extend(BW + 1);
9583 LRes.setIsSigned(
true);
9586 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
9588 LRes = LRes.trunc(BW);
9590 NeedToReorganize = NoNeedToConvert;
9593 bool IsUpperConst =
false;
9594 if (std::optional<llvm::APSInt> Res =
9597 IsUpperConst =
true;
9599 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
9600 (!RoundToStep || IsStepConst)) {
9601 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
9602 : URes.getBitWidth();
9603 LRes = LRes.extend(BW + 1);
9604 LRes.setIsSigned(
true);
9605 URes = URes.extend(BW + 1);
9606 URes.setIsSigned(
true);
9608 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
9609 NeedToReorganize = NoNeedToConvert;
9614 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
9620 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
9623 SemaRef.
Context, LowerSize > UpperSize ? LowerSize : UpperSize,
9635 if (!Lower || !Upper || NewStep.
isInvalid())
9644 if (TestIsStrictOp && InitDependOnLC.has_value() &&
9645 InitDependOnLC.value() >= 2 && !CondDependOnLC.has_value()) {
9646 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
9661 if (NeedToReorganize) {
9695 S, DefaultLoc, BO_Add, Diff.
get(),
9705 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.
get());
9709 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
9725 S, DefaultLoc, BO_Sub, Diff.
get(),
9745 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Div, Diff.
get(), NewStep.
get());
9753Expr *OpenMPIterationSpaceChecker::buildNumIterations(
9755 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9764 if (InitDependOnLC) {
9765 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
9766 if (!IS.MinValue || !IS.MaxValue)
9775 IS.CounterVar, MinValue.
get());
9780 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.
get(), LBVal);
9795 IS.CounterVar, MaxValue.
get());
9800 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.
get(), LBVal);
9809 tryBuildCapture(SemaRef, LBMinVal.
get(), Captures,
".lb_min").get();
9811 tryBuildCapture(SemaRef, LBMaxVal.
get(), Captures,
".lb_max").get();
9812 if (!LBMin || !LBMax)
9816 SemaRef.
BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
9820 tryBuildCapture(SemaRef, MinLessMaxRes.
get(), Captures,
".min_less_max")
9824 if (*TestIsLessOp) {
9828 MinLessMax, LBMin, LBMax);
9831 LBVal = MinLB.
get();
9836 MinLessMax, LBMax, LBMin);
9839 LBVal = MaxLB.
get();
9843 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
9846 LBVal = LBMinVal.
get();
9850 if (CondDependOnLC) {
9851 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9852 if (!IS.MinValue || !IS.MaxValue)
9861 IS.CounterVar, MinValue.
get());
9866 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.
get(), UBVal);
9881 IS.CounterVar, MaxValue.
get());
9886 SemaRef.
BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.
get(), UBVal);
9895 tryBuildCapture(SemaRef, UBMinVal.
get(), Captures,
".ub_min").get();
9897 tryBuildCapture(SemaRef, UBMaxVal.
get(), Captures,
".ub_max").get();
9898 if (!UBMin || !UBMax)
9902 SemaRef.
BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9905 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.
get(),
9906 Captures,
".min_greater_max")
9910 if (*TestIsLessOp) {
9914 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9917 UBVal = MaxUB.
get();
9922 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9925 UBVal = MinUB.
get();
9928 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9929 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9930 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures,
".upper").get();
9931 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures,
".lower").get();
9932 if (!Upper || !Lower)
9936 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9937 true, Captures, InitDependOnLC, CondDependOnLC);
9945 C.getTypeSize(
Type) >
C.getTypeSize(VarType);
9948 UseVarType ?
C.getTypeSize(VarType) :
C.getTypeSize(
Type);
9961 unsigned NewSize = (
C.getTypeSize(
Type) > 32) ? 64 : 32;
9962 if (NewSize !=
C.getTypeSize(
Type)) {
9963 if (NewSize <
C.getTypeSize(
Type)) {
9964 assert(NewSize == 64 &&
"incorrect loop var size");
9965 SemaRef.
Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9966 << InitSrcRange << ConditionSrcRange;
9968 QualType NewType =
C.getIntTypeForBitwidth(
9970 C.getTypeSize(
Type) < NewSize);
9984std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9985 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
9989 return std::make_pair(
nullptr,
nullptr);
9992 Expr *MinExpr =
nullptr;
9993 Expr *MaxExpr =
nullptr;
9994 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9995 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9997 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9999 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
10001 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
10003 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
10004 if (!Upper || !Lower)
10005 return std::make_pair(
nullptr,
nullptr);
10016 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
10017 false, Captures, InitDependOnLC, CondDependOnLC);
10020 return std::make_pair(
nullptr,
nullptr);
10026 return std::make_pair(
nullptr,
nullptr);
10028 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures,
".new_step");
10030 return std::make_pair(
nullptr,
nullptr);
10031 Diff = SemaRef.
BuildBinOp(S, DefaultLoc, BO_Mul, Diff.
get(), NewStep.
get());
10033 return std::make_pair(
nullptr,
nullptr);
10038 return std::make_pair(
nullptr,
nullptr);
10050 return std::make_pair(
nullptr,
nullptr);
10052 if (*TestIsLessOp) {
10056 S, DefaultLoc, BO_Add,
10060 return std::make_pair(
nullptr,
nullptr);
10065 S, DefaultLoc, BO_Sub,
10069 return std::make_pair(
nullptr,
nullptr);
10078 return std::make_pair(
nullptr,
nullptr);
10083 return std::make_pair(
nullptr,
nullptr);
10086 MaxExpr = Diff.
get();
10088 MinExpr = Diff.
get();
10090 return std::make_pair(MinExpr, MaxExpr);
10093Expr *OpenMPIterationSpaceChecker::buildFinalCondition(
Scope *S)
const {
10094 if (InitDependOnLC || CondDependOnLC)
10099Expr *OpenMPIterationSpaceChecker::buildPreCond(
10101 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures)
const {
10106 if (CondDependOnLC || InitDependOnLC)
10117 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
10118 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
10124 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
10125 : (TestIsStrictOp ? BO_GT : BO_GE),
10126 NewLB.
get(), NewUB.
get());
10137 return CondExpr.
isUsable() ? CondExpr.
get() : Cond;
10141DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
10142 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
10143 DSAStackTy &DSA)
const {
10144 auto *VD = dyn_cast<VarDecl>(LCDecl);
10149 const DSAStackTy::DSAVarData
Data =
10150 DSA.getTopDSA(LCDecl,
false);
10154 Captures.insert(std::make_pair(LCRef, Ref));
10160Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar()
const {
10177Expr *OpenMPIterationSpaceChecker::buildCounterInit()
const {
return LB; }
10180Expr *OpenMPIterationSpaceChecker::buildCounterStep()
const {
return Step; }
10182Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
10184 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
SourceLocation Loc,
10190 assert((OOK == OO_Plus || OOK == OO_Minus) &&
10191 "Expected only + or - operations for depend clauses.");
10203 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
10205 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
10206 if (!Upper || !Lower)
10210 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
10212 Captures, InitDependOnLC, CondDependOnLC);
10222 assert(
getLangOpts().OpenMP &&
"OpenMP is not active.");
10223 assert(
Init &&
"Expected loop in canonical form.");
10224 unsigned AssociatedLoops =
DSAStack->getAssociatedLoops();
10231 OpenMPIterationSpaceChecker ISC(
SemaRef,
true,
10234 if (!ISC.checkAndSetInit(
Init,
false)) {
10235 if (
ValueDecl *D = ISC.getLoopDecl()) {
10236 auto *VD = dyn_cast<VarDecl>(D);
10247 DSAStack->addLoopControlVariable(D, VD);
10249 if (LD != D->getCanonicalDecl()) {
10250 DSAStack->resetPossibleLoopCounter();
10251 if (
auto *Var = dyn_cast_or_null<VarDecl>(LD))
10264 DSAStackTy::DSAVarData DVar =
10268 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
10271 ? (
DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
10274 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
10277 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
10279 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
10281 IsOpenMPTaskloopDirective(DKind) ||
10284 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
10285 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
10287 Diag(
Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
10289 << getOpenMPDirectiveName(DKind, OMPVersion)
10291 if (DVar.RefExpr ==
nullptr)
10292 DVar.CKind = PredeterminedCKind;
10294 }
else if (LoopDeclRefExpr) {
10299 if (DVar.CKind == OMPC_unknown)
10300 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
10304 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
10309class OMPDoacrossKind {
10312 return C->getDependenceType() == OMPC_DOACROSS_source ||
10313 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
10316 return C->getDependenceType() == OMPC_DOACROSS_sink;
10318 bool isSinkIter(
const OMPDoacrossClause *
C) {
10319 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
10327 unsigned CurrentNestedLoopCount,
unsigned NestedLoopCount,
10328 unsigned TotalNestedLoopCount,
Expr *CollapseLoopCountExpr,
10329 Expr *OrderedLoopCountExpr,
10332 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
10333 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls,
10334 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars) {
10348 if (
auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
10349 S = CanonLoop->getLoopStmt();
10350 const OMPInvariantPredicateBoundAttr *IntraTileHint =
10351 OMPLoopBasedDirective::getIntraTileHint(S);
10353 S = OMPLoopBasedDirective::ignoreIntraTileHint(S);
10354 Expr *TileRectCond =
nullptr;
10355 Expr *TileBodyPredicate =
nullptr;
10356 Expr *TileTripCount =
nullptr;
10358 TileRectCond = IntraTileHint->getRectCond();
10359 TileBodyPredicate = IntraTileHint->getPredicate();
10360 TileTripCount = IntraTileHint->getTileSize();
10362 auto *For = dyn_cast_or_null<ForStmt>(S);
10363 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
10365 if (!For && (SemaRef.
LangOpts.OpenMP <= 45 || !CXXFor)) {
10368 << (CollapseLoopCountExpr !=
nullptr || OrderedLoopCountExpr !=
nullptr)
10369 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
10370 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
10371 if (TotalNestedLoopCount > 1) {
10372 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
10373 SemaRef.
Diag(DSA.getConstructLoc(),
10374 diag::note_omp_collapse_ordered_expr)
10377 else if (CollapseLoopCountExpr)
10379 diag::note_omp_collapse_ordered_expr)
10381 else if (OrderedLoopCountExpr)
10383 diag::note_omp_collapse_ordered_expr)
10388 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
10394 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
10395 For ? For->getForLoc() : CXXFor->getForLoc(),
10396 CollapsedLoopVarDecls,
10397 CollapsedLoopInductionVars);
10400 Stmt *
Init = For ? For->getInit() : CXXFor->getBeginStmt();
10401 if (ISC.checkAndSetInit(
Init))
10404 bool HasErrors =
false;
10408 Expr *EffectiveCond =
10409 TileRectCond ? TileRectCond : (For ? For->getCond() : CXXFor->getCond());
10412 if (
ValueDecl *LCDecl = ISC.getLoopDecl()) {
10422 SemaRef.
Diag(
Init->getBeginLoc(), diag::err_omp_loop_variable_type)
10436 VarsWithImplicitDSA.erase(LCDecl);
10440 "DSA for non-loop vars");
10443 HasErrors |= ISC.checkAndSetCond(EffectiveCond);
10446 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
10459 if (TileRectCond) {
10460 ResultIterSpaces[CurrentNestedLoopCount].PreCond =
10467 ResultIterSpaces[CurrentNestedLoopCount].NumIterations = TileTripCount;
10469 ResultIterSpaces[CurrentNestedLoopCount].PreCond =
10470 ISC.buildPreCond(DSA.getCurScope(), EffectiveCond, Captures);
10471 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
10472 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
10480 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
10481 ISC.buildCounterVar(Captures, DSA);
10482 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
10483 ISC.buildPrivateCounterVar();
10484 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
10485 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
10486 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
10487 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
10488 ISC.getConditionSrcRange();
10489 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
10490 ISC.getIncrementSrcRange();
10491 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
10492 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
10493 ISC.isStrictTestOp();
10494 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
10495 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
10496 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
10497 if (TileRectCond) {
10500 assert(!ISC.buildFinalCondition(DSA.getCurScope()) &&
10501 "intra-tile floor is not a registered loop-control variable");
10502 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition = TileBodyPredicate;
10506 bool FoundFloor =
false;
10507 if (
Expr *InitExpr = ResultIterSpaces[CurrentNestedLoopCount].CounterInit) {
10508 if (
const auto *LBRef =
10509 dyn_cast<DeclRefExpr>(InitExpr->IgnoreParenImpCasts())) {
10511 for (
unsigned K = 0; K < CurrentNestedLoopCount; ++K) {
10513 dyn_cast_or_null<DeclRefExpr>(ResultIterSpaces[K].CounterVar);
10514 if (CV && CV->getDecl()->getCanonicalDecl() == FloorDecl) {
10515 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
true;
10516 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx = K + 1;
10529 SemaRef.
Diag(ISC.getInitSrcRange().getBegin(),
10530 diag::err_omp_collapse_stacked_tile)
10535 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
10536 ISC.buildFinalCondition(DSA.getCurScope());
10537 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
10538 ISC.doesInitDependOnLC();
10539 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
10540 ISC.doesCondDependOnLC();
10541 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
10542 ISC.getLoopDependentIdx();
10546 (ResultIterSpaces[CurrentNestedLoopCount].PreCond ==
nullptr ||
10547 ResultIterSpaces[CurrentNestedLoopCount].NumIterations ==
nullptr ||
10548 ResultIterSpaces[CurrentNestedLoopCount].CounterVar ==
nullptr ||
10549 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar ==
nullptr ||
10550 ResultIterSpaces[CurrentNestedLoopCount].CounterInit ==
nullptr ||
10551 ResultIterSpaces[CurrentNestedLoopCount].CounterStep ==
nullptr);
10552 if (!HasErrors && DSA.isOrderedRegion()) {
10553 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
10554 if (CurrentNestedLoopCount <
10555 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
10556 DSA.getOrderedRegionParam().second->setLoopNumIterations(
10557 CurrentNestedLoopCount,
10558 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
10559 DSA.getOrderedRegionParam().second->setLoopCounter(
10560 CurrentNestedLoopCount,
10561 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
10564 for (
auto &Pair : DSA.getDoacrossDependClauses()) {
10565 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
10566 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
10567 unsigned NumLoops =
10568 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
10569 if (CurrentNestedLoopCount >= NumLoops) {
10573 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
10574 Pair.second.size() <= CurrentNestedLoopCount) {
10576 DependC->setLoopData(CurrentNestedLoopCount,
nullptr);
10579 OMPDoacrossKind ODK;
10580 if (DoacrossC && ODK.isSink(DoacrossC) &&
10581 Pair.second.size() <= CurrentNestedLoopCount) {
10583 DoacrossC->setLoopData(CurrentNestedLoopCount,
nullptr);
10588 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
10589 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
10590 (DoacrossC && ODK.isSource(DoacrossC)))
10591 CntValue = ISC.buildOrderedLoopData(
10593 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10595 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
10596 Expr *Cnt = SemaRef
10598 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
10606 CntValue = ISC.buildOrderedLoopData(
10608 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10609 DepLoc, Inc, clang::OO_Minus);
10611 CntValue = ISC.buildOrderedLoopData(
10613 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10614 DepLoc, Pair.second[CurrentNestedLoopCount].first,
10615 Pair.second[CurrentNestedLoopCount].second);
10617 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
10619 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
10623 if (CurrentNestedLoopCount < NestedLoopCount && !HasErrors) {
10624 if (
const ValueDecl *LCDecl = ISC.getLoopDecl())
10634 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
10638 : tryBuildCapture(SemaRef, Start.
get(), Captures);
10659 bool IsNonRectangularLB,
10660 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures =
nullptr) {
10669 NewStep = tryBuildCapture(SemaRef, Step.
get(), *Captures);
10684 if (Captures && !IsNonRectangularLB)
10685 NewStart = tryBuildCapture(SemaRef, Start.
get(), *Captures);
10694 Update.get()->getType()->isOverloadableType()) {
10699 if (
Update.isUsable()) {
10701 SemaRef.
BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
10702 VarRef.
get(), SavedUpdate.
get());
10713 NewStart.
get(), SavedUpdate.
get());
10738 unsigned HasBits =
C.getTypeSize(OldType);
10739 if (HasBits >= Bits)
10742 QualType NewType =
C.getIntTypeForBitwidth(Bits,
true);
10752 if (std::optional<llvm::APSInt>
Result =
10761 if (!PreInits.empty()) {
10782 if (
auto *CS = dyn_cast<CompoundStmt>(Item))
10791 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
10792 if (!Captures.empty()) {
10794 for (
const auto &Pair : Captures)
10795 PreInits.push_back(Pair.second->getDecl());
10803 if (PreInits.empty())
10807 for (
Stmt *S : PreInits)
10814 Expr *PostUpdate =
nullptr;
10815 if (!PostUpdates.empty()) {
10816 for (
Expr *E : PostUpdates) {
10822 PostUpdate = PostUpdate
10836 int NestingDepth = 0;
10837 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
10859 if (NestingDepth > 0)
10860 VarDecls.insert(
C);
10870 Expr *OrderedLoopCountExpr,
Stmt *AStmt,
Sema &SemaRef,
10873 OMPLoopBasedDirective::HelperExprs &Built) {
10877 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->
containsErrors()) ||
10878 (OrderedLoopCountExpr && OrderedLoopCountExpr->
containsErrors()))
10881 unsigned NestedLoopCount = 1;
10882 bool SupportsNonPerfectlyNested = (SemaRef.
LangOpts.OpenMP >= 50) &&
10887 if (CollapseLoopCountExpr) {
10892 NestedLoopCount =
Result.Val.getInt().getLimitedValue();
10901 unsigned OrderedLoopCount = 1;
10902 if (OrderedLoopCountExpr) {
10909 if (
Result.getLimitedValue() < NestedLoopCount) {
10911 diag::err_omp_wrong_ordered_loop_count)
10914 diag::note_collapse_loop_count)
10917 OrderedLoopCount =
Result.getLimitedValue();
10925 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
10926 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
10928 if (!OMPLoopBasedDirective::doForAllLoops(
10931 SupportsNonPerfectlyNested, NumLoops,
10932 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10933 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10934 &IterSpaces, &Captures, &CollapsedLoopVarDecls,
10935 &CollapsedLoopInductionVars](
unsigned Cnt,
Stmt *
Loop,
10936 Stmt *HintWrapper) {
10937 Stmt *CurStmt = HintWrapper ? HintWrapper :
Loop;
10939 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
10940 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10941 VarsWithImplicitDSA, IterSpaces, Captures,
10942 CollapsedLoopVarDecls, CollapsedLoopInductionVars))
10944 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10945 IterSpaces[Cnt].CounterVar) {
10949 Captures[DRE] = DRE;
10955 Stmt *DependentPreInits = Transform->getPreInits();
10956 if (!DependentPreInits)
10963 for (
Stmt *S : Constituents) {
10964 if (
auto *DC = dyn_cast<DeclStmt>(S)) {
10965 for (
Decl *
C : DC->decls()) {
10968 SemaRef, D, D->getType().getNonReferenceType(),
10971 Captures[Ref] = Ref;
10978 Built.clear(NestedLoopCount);
10981 return NestedLoopCount;
11014 auto PreCond =
ExprResult(IterSpaces[0].PreCond);
11016 unsigned FirstCountBits =
11017 C.getTypeSize(IterSpaces[0].NumIterations->getType());
11018 bool AllCountsNeedLessThan32Bits = FirstCountBits < 32;
11020 Scope *CurScope = DSA.getCurScope();
11021 for (
unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
11022 if (PreCond.isUsable()) {
11024 SemaRef.
BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
11025 PreCond.get(), IterSpaces[Cnt].PreCond);
11027 Expr *N = IterSpaces[Cnt].NumIterations;
11028 AllCountsNeedLessThan32Bits &=
C.getTypeSize(N->
getType()) < 32;
11031 auto BuildLastIteration = [&](
unsigned Bits) ->
ExprResult {
11033 for (
unsigned Cnt : llvm::seq<unsigned>(NestedLoopCount)) {
11034 Expr *N = IterSpaces[Cnt].NumIterations;
11060 if (SemaRef.
getLangOpts().OpenMPOptimisticCollapse ||
11061 AllCountsNeedLessThan32Bits ||
11062 (NestedLoopCount == 1 && FirstCountBits == 32)) {
11063 LastIteration = BuildLastIteration(32);
11065 ExprResult LastIteration64 = BuildLastIteration(64);
11067 return NestedLoopCount;
11068 LastIteration = LastIteration64;
11070 ExprResult LastIteration32 = BuildLastIteration(32);
11072 C.getTypeSize(LastIteration32.
get()->
getType()) == 32 &&
11075 LastIteration32.
get()
11078 LastIteration64.
get(), SemaRef))
11079 LastIteration = LastIteration32;
11083 return NestedLoopCount;
11100 LastIteration.
get(),
11112 tryBuildCapture(SemaRef, LastIteration.
get(), Captures);
11113 LastIteration = SaveRef;
11126 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
11155 buildVarDecl(SemaRef, InitLoc, StrideVType,
".omp.stride");
11164 UB.
get(), LastIteration.
get());
11167 LastIteration.
get(), UB.
get());
11168 EUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, UB.
get(),
11179 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.lb");
11187 buildVarDecl(SemaRef, InitLoc, VType,
".omp.comb.ub");
11193 CurScope, InitLoc, BO_GT, CombUB.
get(), LastIteration.
get());
11196 LastIteration.
get(), CombUB.
get());
11197 CombEUB = SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.
get(),
11206 "Unexpected number of parameters in loop combined directive");
11247 SemaRef.
BuildBinOp(CurScope, InitLoc, BO_Assign, IV.
get(), CombRHS);
11253 bool UseStrictCompare =
11255 llvm::all_of(IterSpaces, [](
const LoopIterationSpace &LIS) {
11256 return LIS.IsStrictCompare;
11262 if (UseStrictCompare) {
11265 .
BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
11277 UseStrictCompare ? BO_LT : BO_LE, IV.
get(),
11280 NumIterations.
get());
11283 CombDistCond = SemaRef.
BuildBinOp(CurScope, CondLoc, BO_LT, IV.
get(),
11284 NumIterations.
get());
11289 Expr *BoundCombUB = CombUB.
get();
11290 if (UseStrictCompare) {
11294 CurScope, CondLoc, BO_Add, BoundCombUB,
11302 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
11303 IV.
get(), BoundCombUB);
11310 if (!Inc.isUsable())
11312 Inc = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, IV.
get(), Inc.get());
11314 if (!Inc.isUsable())
11321 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
11327 NextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, LB.
get(), ST.
get());
11338 NextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Add, UB.
get(), ST.
get());
11354 CombNextLB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.
get(),
11366 CombNextUB = SemaRef.
BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.
get(),
11380 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
11383 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.
get(), BoundUB);
11384 assert(DistCond.
isUsable() &&
"distribute cond expr was not built");
11388 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
11389 DistInc = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.
get(),
11393 assert(DistInc.
isUsable() &&
"distribute inc expr was not built");
11404 DistEUBLoc, NewPrevUB.
get());
11409 UB.
get(), NewPrevUB.
get());
11411 DistEUBLoc, DistEUBLoc, IsUBGreater.
get(), NewPrevUB.
get(), UB.
get());
11412 PrevEUB = SemaRef.
BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.
get(),
11420 Expr *BoundPrevUB = PrevUB.
get();
11421 if (UseStrictCompare) {
11425 CurScope, CondLoc, BO_Add, BoundPrevUB,
11433 SemaRef.
BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
11434 IV.
get(), BoundPrevUB);
11438 bool HasErrors =
false;
11439 Built.Counters.resize(NestedLoopCount);
11440 Built.Inits.resize(NestedLoopCount);
11441 Built.Updates.resize(NestedLoopCount);
11442 Built.Finals.resize(NestedLoopCount);
11443 Built.DependentCounters.resize(NestedLoopCount);
11444 Built.DependentInits.resize(NestedLoopCount);
11445 Built.FinalsConditions.resize(NestedLoopCount);
11463 for (
unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
11464 LoopIterationSpace &IS = IterSpaces[Cnt];
11470 for (
unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
11471 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.
get(),
11472 IterSpaces[K].NumIterations);
11477 if (Cnt + 1 < NestedLoopCount)
11491 if (Cnt + 1 < NestedLoopCount)
11492 Prod = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.
get(),
11496 Acc = SemaRef.
BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.
get(), Prod.
get());
11505 IS.CounterInit, IS.IsNonRectangularLB, Captures);
11506 if (!
Init.isUsable()) {
11511 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
11512 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
11513 if (!
Update.isUsable()) {
11521 IS.CounterInit, IS.NumIterations, IS.CounterStep,
11522 IS.Subtract, IS.IsNonRectangularLB, &Captures);
11523 if (!Final.isUsable()) {
11528 if (!
Update.isUsable() || !Final.isUsable()) {
11533 Built.Counters[Cnt] = IS.CounterVar;
11534 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
11535 Built.Inits[Cnt] =
Init.get();
11536 Built.Updates[Cnt] =
Update.get();
11537 Built.Finals[Cnt] = Final.get();
11538 Built.DependentCounters[Cnt] =
nullptr;
11539 Built.DependentInits[Cnt] =
nullptr;
11543 Built.FinalsConditions[Cnt] = IS.FinalCondition;
11544 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
11545 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
11546 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
11555 Built.IterationVarRef = IV.
get();
11556 Built.LastIteration = LastIteration.
get();
11557 Built.NumIterations = NumIterations.
get();
11558 Built.CalcLastIteration = SemaRef
11562 Built.PreCond = PreCond.get();
11564 Built.Cond = Cond.
get();
11565 Built.Init =
Init.get();
11566 Built.Inc = Inc.get();
11567 Built.LB = LB.
get();
11568 Built.UB = UB.
get();
11569 Built.IL = IL.
get();
11570 Built.ST = ST.
get();
11571 Built.EUB = EUB.
get();
11572 Built.NLB = NextLB.
get();
11573 Built.NUB = NextUB.
get();
11574 Built.PrevLB = PrevLB.
get();
11575 Built.PrevUB = PrevUB.
get();
11576 Built.DistInc = DistInc.
get();
11577 Built.PrevEUB = PrevEUB.
get();
11578 Built.DistCombinedFields.LB = CombLB.
get();
11579 Built.DistCombinedFields.UB = CombUB.
get();
11580 Built.DistCombinedFields.EUB = CombEUB.
get();
11581 Built.DistCombinedFields.Init = CombInit.
get();
11582 Built.DistCombinedFields.Cond = CombCond.
get();
11583 Built.DistCombinedFields.NLB = CombNextLB.
get();
11584 Built.DistCombinedFields.NUB = CombNextUB.
get();
11585 Built.DistCombinedFields.DistCond = CombDistCond.
get();
11586 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.
get();
11588 return NestedLoopCount;
11592 auto CollapseClauses =
11593 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
11594 if (CollapseClauses.begin() != CollapseClauses.end())
11595 return (*CollapseClauses.begin())->getNumForLoops();
11600 auto OrderedClauses =
11601 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
11602 if (OrderedClauses.begin() != OrderedClauses.end())
11603 return (*OrderedClauses.begin())->getNumForLoops();
11612 for (
const OMPClause *Clause : Clauses) {
11613 if (Clause->getClauseKind() == OMPC_safelen)
11615 else if (Clause->getClauseKind() == OMPC_simdlen)
11617 if (Safelen && Simdlen)
11621 if (Simdlen && Safelen) {
11635 llvm::APSInt SimdlenRes = SimdlenResult.
Val.
getInt();
11636 llvm::APSInt SafelenRes = SafelenResult.
Val.
getInt();
11641 if (llvm::APSInt::compareValues(SimdlenRes, SafelenRes) > 0) {
11643 diag::err_omp_wrong_simdlen_safelen_values)
11660 OMPLoopBasedDirective::HelperExprs B;
11666 if (NestedLoopCount == 0)
11676 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11677 return SimdDirective;
11687 OMPLoopBasedDirective::HelperExprs B;
11693 if (NestedLoopCount == 0)
11700 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11702 return ForDirective;
11714 OMPLoopBasedDirective::HelperExprs B;
11717 unsigned NestedLoopCount =
11720 VarsWithImplicitDSA, B);
11721 if (NestedLoopCount == 0)
11731 NestedLoopCount, Clauses, AStmt, B);
11735 Stmt *AStmt, DSAStackTy *Stack) {
11741 auto BaseStmt = AStmt;
11742 while (
auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11744 if (
auto *
C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11745 auto S =
C->children();
11746 if (S.begin() == S.end())
11750 for (
Stmt *SectionStmt : llvm::drop_begin(S)) {
11753 SemaRef.
Diag(SectionStmt->getBeginLoc(),
11754 diag::err_omp_sections_substmt_not_section)
11755 << getOpenMPDirectiveName(DKind, OMPVersion);
11759 ->setHasCancel(Stack->isCancelRegion());
11762 SemaRef.
Diag(AStmt->
getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
11763 << getOpenMPDirectiveName(DKind, OMPVersion);
11776 SemaRef.setFunctionHasBranchProtectedScope();
11789 SemaRef.setFunctionHasBranchProtectedScope();
11798 if (
auto *CE = dyn_cast<CallExpr>(E))
11799 if (CE->getDirectCallee())
11820 if (!
SemaRef.CurContext->isDependentContext()) {
11821 Expr *TargetCall =
nullptr;
11823 auto *E = dyn_cast<Expr>(S);
11831 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
11832 if (BO->getOpcode() == BO_Assign)
11835 if (
auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
11836 if (COCE->getOperator() == OO_Equal)
11848 SemaRef.setFunctionHasBranchProtectedScope();
11851 Clauses, AStmt, TargetCallLoc);
11856 DSAStackTy *Stack) {
11857 bool ErrorFound =
false;
11859 if (
auto *LPC = dyn_cast<OMPLastprivateClause>(
C)) {
11860 for (
Expr *RefExpr : LPC->varlist()) {
11863 Expr *SimpleRefExpr = RefExpr;
11866 auto &&Info = Stack->isLoopControlVariable(D);
11869 S.
Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
11870 << getOpenMPDirectiveName(K, OMPVersion);
11894 OMPLoopDirective::HelperExprs B;
11899 if (NestedLoopCount == 0)
11902 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11903 "omp loop exprs were not built");
11906 NestedLoopCount, Clauses, AStmt, B);
11915 const uint64_t NumVars = ClauseVarList.size();
11920 SemaRef.
Diag(ClauseBeginLoc,
11921 diag::err_ompx_more_than_three_expr_not_allowed)
11922 << getOpenMPClauseName(ClauseKind);
11929 uint64_t MaxExprs = 1;
11930 if (DimsModifierExpr) {
11940 if (NumVars != MaxExprs) {
11941 SemaRef.
Diag(ClauseBeginLoc, diag::err_omp_unexpected_num_exprs)
11942 << getOpenMPClauseName(ClauseKind) << MaxExprs << NumVars;
11946 SemaRef.
Diag(ClauseBeginLoc, diag::err_omp_max_three_exprs)
11947 << getOpenMPClauseName(ClauseKind);
11955template <
typename ClauseT>
11957 const ClauseT *Clause,
11962 SemaRef, Clause->getClauseKind(), Clause->getBeginLoc(),
11963 Clause->getVarRefs(), Clause->getDimsModifierExpr(), BareClause);
11971 bool MayHaveBareClause =
false) {
11972 auto BareClauseIt =
11973 MayHaveBareClause ? llvm::find_if(Clauses, llvm::IsaPred<OMPXBareClause>)
11975 auto ThreadLimitIt =
11976 llvm::find_if(Clauses, llvm::IsaPred<OMPThreadLimitClause>);
11977 auto NumTeamsIt = llvm::find_if(Clauses, llvm::IsaPred<OMPNumTeamsClause>);
11979 const auto *BareClause = BareClauseIt != Clauses.end()
11982 const auto *ThreadLimitClause =
11983 ThreadLimitIt != Clauses.end()
11986 const auto *NumTeamsClause = NumTeamsIt != Clauses.end()
11991 if (!NumTeamsClause || !ThreadLimitClause) {
11992 SemaRef.
Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
11995 if (ThreadLimitClause->getModifier() == OMPC_THREADLIMIT_dims ||
11996 NumTeamsClause->getModifier() == OMPC_NUMTEAMS_dims) {
11997 SemaRef.
Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_dims);
12025 OMPLoopDirective::HelperExprs B;
12027 unsigned NestedLoopCount =
12030 VarsWithImplicitDSA, B);
12031 if (NestedLoopCount == 0)
12034 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
12035 "omp loop exprs were not built");
12037 DSAStack->setParentTeamsRegionLoc(StartLoc);
12040 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
12069 OMPLoopDirective::HelperExprs B;
12071 unsigned NestedLoopCount =
12074 VarsWithImplicitDSA, B);
12075 if (NestedLoopCount == 0)
12078 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
12079 "omp loop exprs were not built");
12082 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12102 OMPLoopDirective::HelperExprs B;
12104 unsigned NestedLoopCount =
12107 VarsWithImplicitDSA, B);
12108 if (NestedLoopCount == 0)
12111 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
12112 "omp loop exprs were not built");
12115 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
12144 OMPLoopDirective::HelperExprs B;
12146 unsigned NestedLoopCount =
12149 VarsWithImplicitDSA, B);
12150 if (NestedLoopCount == 0)
12153 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
12154 "omp loop exprs were not built");
12157 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
12169 SemaRef.setFunctionHasBranchProtectedScope();
12174 const OMPClause *Copyprivate =
nullptr;
12175 for (
const OMPClause *Clause : Clauses) {
12176 if (Clause->getClauseKind() == OMPC_nowait)
12178 else if (Clause->getClauseKind() == OMPC_copyprivate)
12179 Copyprivate = Clause;
12180 if (Copyprivate && Nowait) {
12182 diag::err_omp_single_copyprivate_with_nowait);
12198 SemaRef.setFunctionHasBranchProtectedScope();
12210 SemaRef.setFunctionHasBranchProtectedScope();
12222 bool ErrorFound =
false;
12225 bool DependentHint =
false;
12227 if (
C->getClauseKind() == OMPC_hint) {
12229 Diag(
C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
12235 DependentHint =
true;
12238 HintLoc =
C->getBeginLoc();
12244 const auto Pair =
DSAStack->getCriticalWithHint(DirName);
12245 if (Pair.first && DirName.
getName() && !DependentHint) {
12246 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
12247 Diag(StartLoc, diag::err_omp_critical_with_hint);
12249 Diag(HintLoc, diag::note_omp_critical_hint_here)
12250 << 0 <<
toString(Hint, 10,
false);
12252 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
12253 if (
const auto *
C = Pair.first->getSingleClause<
OMPHintClause>()) {
12254 Diag(
C->getBeginLoc(), diag::note_omp_critical_hint_here)
12259 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
12264 SemaRef.setFunctionHasBranchProtectedScope();
12267 EndLoc, Clauses, AStmt);
12268 if (!Pair.first && DirName.
getName() && !DependentHint)
12269 DSAStack->addCriticalWithHint(Dir, Hint);
12281 OMPLoopBasedDirective::HelperExprs B;
12284 unsigned NestedLoopCount =
12287 VarsWithImplicitDSA, B);
12288 if (NestedLoopCount == 0)
12295 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12308 OMPLoopBasedDirective::HelperExprs B;
12311 unsigned NestedLoopCount =
12314 VarsWithImplicitDSA, B);
12315 if (NestedLoopCount == 0)
12325 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
12338 DSAStack->getTaskgroupReductionRef());
12351 DSAStack->getTaskgroupReductionRef());
12360 SemaRef.setFunctionHasBranchProtectedScope();
12372 bool ErrorFound =
false;
12374 if (llvm::is_contained(MutuallyExclusiveClauses,
C->getClauseKind())) {
12378 S.
Diag(
C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
12401 {OMPC_detach, OMPC_mergeable}))
12411 AStmt,
DSAStack->isCancelRegion());
12427 bool InExContext) {
12428 const OMPAtClause *AtC =
12429 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
12431 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
12432 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
12436 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
12437 const OMPSeverityClause *SeverityC =
12438 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
12439 const OMPMessageClause *MessageC =
12440 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
12441 std::optional<std::string> SL =
12442 MessageC ? MessageC->tryEvaluateString(
getASTContext()) : std::nullopt;
12444 if (MessageC && !SL)
12445 Diag(MessageC->getMessageString()->getBeginLoc(),
12446 diag::warn_clause_expected_string)
12448 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
12449 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
12450 << SL.value_or(
"WARNING");
12452 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or(
"ERROR");
12453 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
12464 const OMPNowaitClause *NowaitC =
12465 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
12467 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
12469 if (NowaitC && !HasDependC) {
12470 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
12487 SemaRef.setFunctionHasBranchProtectedScope();
12491 DSAStack->getTaskgroupReductionRef());
12500 if (
C->getClauseKind() == OMPC_flush)
12509 if (
C->getClauseKind() == OMPC_acq_rel ||
12510 C->getClauseKind() == OMPC_acquire ||
12511 C->getClauseKind() == OMPC_release ||
12512 C->getClauseKind() == OMPC_seq_cst ) {
12513 if (MemOrderKind != OMPC_unknown) {
12514 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12515 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
12517 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12520 MemOrderKind =
C->getClauseKind();
12521 MemOrderLoc =
C->getBeginLoc();
12525 if (FC && OrderClause) {
12526 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
12528 Diag(OrderClause->
getBeginLoc(), diag::note_omp_flush_order_clause_here)
12538 if (Clauses.empty()) {
12539 Diag(StartLoc, diag::err_omp_depobj_expected);
12541 }
else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
12542 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
12546 if (Clauses.size() > 2) {
12547 Diag(Clauses[2]->getBeginLoc(),
12548 diag::err_omp_depobj_single_clause_expected);
12550 }
else if (Clauses.size() < 1) {
12551 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
12561 if (Clauses.size() != 1) {
12562 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
12563 diag::err_omp_scan_single_clause_expected);
12572 return StmtError(
Diag(StartLoc, diag::err_omp_orphaned_device_directive)
12573 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
12578 if (
DSAStack->doesParentHasScanDirective()) {
12579 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"scan";
12581 diag::note_omp_previous_directive)
12585 DSAStack->setParentHasScanDirective(StartLoc);
12593 const OMPClause *DependFound =
nullptr;
12594 const OMPClause *DependSourceClause =
nullptr;
12595 const OMPClause *DependSinkClause =
nullptr;
12596 const OMPClause *DoacrossFound =
nullptr;
12597 const OMPClause *DoacrossSourceClause =
nullptr;
12598 const OMPClause *DoacrossSinkClause =
nullptr;
12599 bool ErrorFound =
false;
12603 auto DOC = dyn_cast<OMPDoacrossClause>(
C);
12604 auto DC = dyn_cast<OMPDependClause>(
C);
12606 DependFound = DC ?
C :
nullptr;
12607 DoacrossFound = DOC ?
C :
nullptr;
12608 OMPDoacrossKind ODK;
12609 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
12610 (DOC && (ODK.isSource(DOC)))) {
12611 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
12613 Diag(
C->getBeginLoc(), diag::err_omp_more_one_clause)
12614 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
12621 DependSourceClause =
C;
12623 DoacrossSourceClause =
C;
12625 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
12626 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
12627 << (DC ?
"depend" :
"doacross") << 0;
12630 }
else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
12631 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
12632 if (DependSourceClause || DoacrossSourceClause) {
12633 Diag(
C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
12634 << (DC ?
"depend" :
"doacross") << 1;
12638 DependSinkClause =
C;
12640 DoacrossSinkClause =
C;
12642 }
else if (
C->getClauseKind() == OMPC_threads) {
12644 }
else if (
C->getClauseKind() == OMPC_simd) {
12648 if (!ErrorFound && !SC &&
12653 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
12656 }
else if ((DependFound || DoacrossFound) && (TC || SC)) {
12659 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
12662 : SC->getClauseKind());
12664 }
else if ((DependFound || DoacrossFound) &&
12665 !
DSAStack->getParentOrderedRegionParam().first) {
12668 Diag(Loc, diag::err_omp_ordered_directive_without_param)
12672 }
else if (TC || Clauses.empty()) {
12673 if (
const Expr *Param =
DSAStack->getParentOrderedRegionParam().first) {
12675 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
12676 << (TC !=
nullptr);
12677 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
12681 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
12689 if (!DependFound && !DoacrossFound) {
12690 if (
DSAStack->doesParentHasOrderedDirective()) {
12691 Diag(StartLoc, diag::err_omp_several_directives_in_region) <<
"ordered";
12693 diag::note_omp_previous_directive)
12697 DSAStack->setParentHasOrderedDirective(StartLoc);
12703 SemaRef.setFunctionHasBranchProtectedScope();
12710 EndLoc, Clauses, AStmt);
12716class OpenMPAtomicUpdateChecker {
12718 enum ExprAnalysisErrorCode {
12722 NotABinaryOrUnaryExpression,
12724 NotAnUnaryIncDecExpression,
12730 NotABinaryExpression,
12733 NotABinaryOperator,
12736 NotAnUpdateExpression,
12739 NotAValidExpression,
12757 bool IsXLHSInRHSPart;
12762 bool IsPostfixUpdate;
12765 OpenMPAtomicUpdateChecker(
Sema &SemaRef)
12767 IsXLHSInRHSPart(
false), Op(BO_PtrMemD), IsPostfixUpdate(
false) {}
12775 bool checkStatement(Stmt *S,
unsigned DiagId = 0,
unsigned NoteId = 0);
12777 Expr *getX()
const {
return X; }
12779 Expr *getExpr()
const {
return E; }
12783 Expr *getUpdateExpr()
const {
return UpdateExpr; }
12786 bool isXLHSInRHSPart()
const {
return IsXLHSInRHSPart; }
12790 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
12793 bool checkBinaryOperation(BinaryOperator *AtomicBinOp,
unsigned DiagId = 0,
12794 unsigned NoteId = 0);
12797bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
12798 BinaryOperator *AtomicBinOp,
unsigned DiagId,
unsigned NoteId) {
12799 ExprAnalysisErrorCode ErrorFound = NoError;
12805 if (AtomicBinOp->
getOpcode() == BO_Assign) {
12807 if (
const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
12809 if (AtomicInnerBinOp->isMultiplicativeOp() ||
12810 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
12811 AtomicInnerBinOp->isBitwiseOp()) {
12812 Op = AtomicInnerBinOp->getOpcode();
12813 OpLoc = AtomicInnerBinOp->getOperatorLoc();
12814 Expr *LHS = AtomicInnerBinOp->getLHS();
12815 Expr *RHS = AtomicInnerBinOp->getRHS();
12816 llvm::FoldingSetNodeID XId, LHSId, RHSId;
12823 if (XId == LHSId) {
12825 IsXLHSInRHSPart =
true;
12826 }
else if (XId == RHSId) {
12828 IsXLHSInRHSPart =
false;
12830 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12831 ErrorRange = AtomicInnerBinOp->getSourceRange();
12832 NoteLoc =
X->getExprLoc();
12833 NoteRange =
X->getSourceRange();
12834 ErrorFound = NotAnUpdateExpression;
12837 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12838 ErrorRange = AtomicInnerBinOp->getSourceRange();
12839 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
12841 ErrorFound = NotABinaryOperator;
12846 ErrorFound = NotABinaryExpression;
12853 ErrorFound = NotAnAssignmentOp;
12855 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12856 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
12857 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
12861 E =
X = UpdateExpr =
nullptr;
12862 return ErrorFound != NoError;
12865bool OpenMPAtomicUpdateChecker::checkStatement(
Stmt *S,
unsigned DiagId,
12867 ExprAnalysisErrorCode ErrorFound = NoError;
12878 if (
auto *AtomicBody = dyn_cast<Expr>(S)) {
12879 AtomicBody = AtomicBody->IgnoreParenImpCasts();
12880 if (AtomicBody->getType()->isScalarType() ||
12881 AtomicBody->isInstantiationDependent()) {
12882 if (
const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
12883 AtomicBody->IgnoreParenImpCasts())) {
12886 AtomicCompAssignOp->getOpcode());
12887 OpLoc = AtomicCompAssignOp->getOperatorLoc();
12888 E = AtomicCompAssignOp->getRHS();
12890 IsXLHSInRHSPart =
true;
12891 }
else if (
auto *AtomicBinOp = dyn_cast<BinaryOperator>(
12892 AtomicBody->IgnoreParenImpCasts())) {
12894 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
12896 }
else if (
const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
12897 AtomicBody->IgnoreParenImpCasts())) {
12899 if (AtomicUnaryOp->isIncrementDecrementOp()) {
12900 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
12901 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
12902 OpLoc = AtomicUnaryOp->getOperatorLoc();
12903 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
12905 IsXLHSInRHSPart =
true;
12907 ErrorFound = NotAnUnaryIncDecExpression;
12908 ErrorLoc = AtomicUnaryOp->getExprLoc();
12909 ErrorRange = AtomicUnaryOp->getSourceRange();
12910 NoteLoc = AtomicUnaryOp->getOperatorLoc();
12913 }
else if (!AtomicBody->isInstantiationDependent()) {
12914 ErrorFound = NotABinaryOrUnaryExpression;
12915 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12916 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12917 }
else if (AtomicBody->containsErrors()) {
12918 ErrorFound = NotAValidExpression;
12919 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12920 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12923 ErrorFound = NotAScalarType;
12924 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
12925 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12928 ErrorFound = NotAnExpression;
12930 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
12932 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12933 SemaRef.
Diag(ErrorLoc, DiagId) << ErrorRange;
12934 SemaRef.
Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
12938 E =
X = UpdateExpr =
nullptr;
12940 !
X->containsErrors()) {
12950 IsXLHSInRHSPart ? OVEExpr : OVEX);
12957 UpdateExpr =
Update.get();
12959 return ErrorFound != NoError;
12963llvm::FoldingSetNodeID getNodeId(
ASTContext &Context,
const Expr *S) {
12964 llvm::FoldingSetNodeID Id;
12970bool checkIfTwoExprsAreSame(
ASTContext &Context,
const Expr *LHS,
12972 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
12975class OpenMPAtomicCompareChecker {
13022 struct ErrorInfoTy {
13024 SourceLocation ErrorLoc;
13025 SourceRange ErrorRange;
13026 SourceLocation NoteLoc;
13027 SourceRange NoteRange;
13030 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
13033 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
13035 Expr *getX()
const {
return X; }
13036 Expr *getE()
const {
return E; }
13037 Expr *getD()
const {
return D; }
13038 Expr *getCond()
const {
return C; }
13039 bool isXBinopExpr()
const {
return IsXBinopExpr; }
13043 ASTContext &ContextRef;
13058 bool IsXBinopExpr =
true;
13061 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
13064 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
13067 bool checkType(ErrorInfoTy &ErrorInfo)
const;
13069 static bool CheckValue(
const Expr *E, ErrorInfoTy &ErrorInfo,
13070 bool ShouldBeLValue,
bool ShouldBeInteger =
false) {
13074 if (ShouldBeLValue && !E->
isLValue()) {
13075 ErrorInfo.Error = ErrorTy::XNotLValue;
13076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
13077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
13083 ErrorInfo.Error = ErrorTy::NotScalar;
13084 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
13085 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
13089 ErrorInfo.Error = ErrorTy::NotInteger;
13090 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->
getExprLoc();
13091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->
getSourceRange();
13099bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(
IfStmt *S,
13100 ErrorInfoTy &ErrorInfo) {
13102 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
13103 if (CS->body_empty()) {
13104 ErrorInfo.Error = ErrorTy::NoStmt;
13105 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13106 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
13109 if (CS->size() > 1) {
13110 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13111 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13112 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
13115 Then = CS->body_front();
13118 auto *BO = dyn_cast<BinaryOperator>(Then);
13120 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13121 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
13122 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
13125 if (BO->getOpcode() != BO_Assign) {
13126 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13127 ErrorInfo.ErrorLoc = BO->getExprLoc();
13128 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13129 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13135 auto *Cond = dyn_cast<BinaryOperator>(S->
getCond());
13136 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
13137 Expr *LHS =
nullptr;
13138 Expr *RHS =
nullptr;
13140 LHS = Cond->getLHS();
13141 RHS = Cond->getRHS();
13143 LHS =
Call->getArg(0);
13144 RHS =
Call->getArg(1);
13146 ErrorInfo.Error = ErrorTy::NotABinaryOp;
13152 if ((Cond && Cond->getOpcode() == BO_EQ) ||
13153 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
13156 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
13158 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
13161 ErrorInfo.Error = ErrorTy::InvalidComparison;
13163 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13167 }
else if ((Cond &&
13168 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
13170 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
13171 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
13173 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
13174 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
13176 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
13177 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
13179 IsXBinopExpr =
false;
13181 ErrorInfo.Error = ErrorTy::InvalidComparison;
13183 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13188 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
13195 ErrorInfo.Error = ErrorTy::UnexpectedElse;
13204bool OpenMPAtomicCompareChecker::checkCondExprStmt(
Stmt *S,
13205 ErrorInfoTy &ErrorInfo) {
13206 auto *BO = dyn_cast<BinaryOperator>(S);
13208 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
13210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
13213 if (BO->getOpcode() != BO_Assign) {
13214 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13215 ErrorInfo.ErrorLoc = BO->getExprLoc();
13216 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13223 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
13225 ErrorInfo.Error = ErrorTy::NotCondOp;
13226 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
13227 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
13231 if (!checkIfTwoExprsAreSame(ContextRef,
X, CO->getFalseExpr())) {
13232 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
13233 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
13234 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13235 CO->getFalseExpr()->getSourceRange();
13239 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
13240 auto *
Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
13241 Expr *LHS =
nullptr;
13242 Expr *RHS =
nullptr;
13244 LHS = Cond->getLHS();
13245 RHS = Cond->getRHS();
13247 LHS =
Call->getArg(0);
13248 RHS =
Call->getArg(1);
13250 ErrorInfo.Error = ErrorTy::NotABinaryOp;
13251 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13252 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13253 CO->getCond()->getSourceRange();
13257 if ((Cond && Cond->getOpcode() == BO_EQ) ||
13258 (
Call &&
Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
13260 D = CO->getTrueExpr();
13261 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
13263 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
13266 ErrorInfo.Error = ErrorTy::InvalidComparison;
13267 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13268 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13269 CO->getCond()->getSourceRange();
13272 }
else if ((Cond &&
13273 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
13275 (
Call->getOperator() == OverloadedOperatorKind::OO_Less ||
13276 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
13278 E = CO->getTrueExpr();
13279 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS) &&
13280 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
13282 }
else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
13283 checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
13285 IsXBinopExpr =
false;
13287 ErrorInfo.Error = ErrorTy::InvalidComparison;
13288 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13289 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13290 CO->getCond()->getSourceRange();
13294 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
13295 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13296 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13297 CO->getCond()->getSourceRange();
13304bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo)
const {
13306 assert(
X && E &&
"X and E cannot be nullptr");
13308 if (!CheckValue(
X, ErrorInfo,
true))
13311 if (!CheckValue(E, ErrorInfo,
false))
13314 if (D && !CheckValue(D, ErrorInfo,
false))
13320bool OpenMPAtomicCompareChecker::checkStmt(
13321 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
13322 auto *CS = dyn_cast<CompoundStmt>(S);
13324 if (CS->body_empty()) {
13325 ErrorInfo.Error = ErrorTy::NoStmt;
13326 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13327 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
13331 if (CS->size() != 1) {
13332 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13333 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13334 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
13337 S = CS->body_front();
13342 if (
auto *IS = dyn_cast<IfStmt>(S)) {
13348 Res = checkCondUpdateStmt(IS, ErrorInfo);
13354 Res = checkCondExprStmt(S, ErrorInfo);
13360 return checkType(ErrorInfo);
13363class OpenMPAtomicCompareCaptureChecker final
13364 :
public OpenMPAtomicCompareChecker {
13366 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
13368 Expr *getV()
const {
return V; }
13369 Expr *getR()
const {
return R; }
13370 bool isFailOnly()
const {
return IsFailOnly; }
13371 bool isPostfixUpdate()
const {
return IsPostfixUpdate; }
13374 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
13377 bool checkType(ErrorInfoTy &ErrorInfo);
13389 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
13393 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
13400 bool IsFailOnly =
false;
13402 bool IsPostfixUpdate =
false;
13405bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
13406 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
13409 if (
V && !CheckValue(
V, ErrorInfo,
true))
13412 if (R && !CheckValue(R, ErrorInfo,
true,
true))
13418bool OpenMPAtomicCompareCaptureChecker::checkForm3(
IfStmt *S,
13419 ErrorInfoTy &ErrorInfo) {
13423 if (
auto *CS = dyn_cast<CompoundStmt>(Then)) {
13424 if (CS->body_empty()) {
13425 ErrorInfo.Error = ErrorTy::NoStmt;
13426 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13427 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
13430 if (CS->size() > 1) {
13431 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13432 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13433 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
13436 Then = CS->body_front();
13439 auto *BO = dyn_cast<BinaryOperator>(Then);
13441 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13442 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
13443 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
13446 if (BO->getOpcode() != BO_Assign) {
13447 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13448 ErrorInfo.ErrorLoc = BO->getExprLoc();
13449 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13457 auto *Cond = dyn_cast<BinaryOperator>(S->
getCond());
13458 auto *
Call = dyn_cast<CXXOperatorCallExpr>(S->
getCond());
13459 Expr *LHS =
nullptr;
13460 Expr *RHS =
nullptr;
13462 LHS = Cond->getLHS();
13463 RHS = Cond->getRHS();
13465 LHS =
Call->getArg(0);
13466 RHS =
Call->getArg(1);
13468 ErrorInfo.Error = ErrorTy::NotABinaryOp;
13473 if ((Cond && Cond->getOpcode() != BO_EQ) ||
13474 (
Call &&
Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
13475 ErrorInfo.Error = ErrorTy::NotEQ;
13481 if (checkIfTwoExprsAreSame(ContextRef,
X, LHS)) {
13483 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, RHS)) {
13486 ErrorInfo.Error = ErrorTy::InvalidComparison;
13495 ErrorInfo.Error = ErrorTy::NoElse;
13496 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
13497 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
13502 if (
auto *CS = dyn_cast<CompoundStmt>(Else)) {
13503 if (CS->body_empty()) {
13504 ErrorInfo.Error = ErrorTy::NoStmt;
13505 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13506 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
13509 if (CS->size() > 1) {
13510 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13511 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13512 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
13515 Else = CS->body_front();
13518 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
13520 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13521 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
13522 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
13525 if (ElseBO->getOpcode() != BO_Assign) {
13526 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13527 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
13528 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
13529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
13533 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
13534 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13535 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
13536 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13537 ElseBO->getRHS()->getSourceRange();
13541 V = ElseBO->getLHS();
13543 return checkType(ErrorInfo);
13546bool OpenMPAtomicCompareCaptureChecker::checkForm45(
Stmt *S,
13547 ErrorInfoTy &ErrorInfo) {
13551 assert(CS->size() == 2 &&
"CompoundStmt size is not expected");
13554 assert(S1->getOpcode() == BO_Assign &&
"unexpected binary operator");
13556 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
13557 ErrorInfo.Error = ErrorTy::InvalidCondition;
13558 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
13559 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
13565 auto *Then = S2->getThen();
13566 if (
auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
13567 if (ThenCS->body_empty()) {
13568 ErrorInfo.Error = ErrorTy::NoStmt;
13569 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
13570 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
13573 if (ThenCS->size() > 1) {
13574 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13575 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
13576 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
13579 Then = ThenCS->body_front();
13582 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
13584 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13585 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
13586 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
13589 if (ThenBO->getOpcode() != BO_Assign) {
13590 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13591 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
13592 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
13593 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
13597 X = ThenBO->getLHS();
13598 D = ThenBO->getRHS();
13601 if (BO->getOpcode() != BO_EQ) {
13602 ErrorInfo.Error = ErrorTy::NotEQ;
13603 ErrorInfo.ErrorLoc = BO->getExprLoc();
13604 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13605 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13611 if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getLHS())) {
13613 }
else if (checkIfTwoExprsAreSame(ContextRef,
X, BO->getRHS())) {
13616 ErrorInfo.Error = ErrorTy::InvalidComparison;
13617 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
13618 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13622 if (S2->getElse()) {
13625 auto *Else = S2->getElse();
13626 if (
auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
13627 if (ElseCS->body_empty()) {
13628 ErrorInfo.Error = ErrorTy::NoStmt;
13629 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
13630 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
13633 if (ElseCS->size() > 1) {
13634 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13635 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
13636 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
13639 Else = ElseCS->body_front();
13642 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
13644 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13645 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
13646 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
13649 if (ElseBO->getOpcode() != BO_Assign) {
13650 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13651 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
13652 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
13653 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
13656 if (!checkIfTwoExprsAreSame(ContextRef,
X, ElseBO->getRHS())) {
13657 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13658 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
13659 ErrorInfo.NoteLoc =
X->getExprLoc();
13660 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
13661 ErrorInfo.NoteRange =
X->getSourceRange();
13665 V = ElseBO->getLHS();
13668 return checkType(ErrorInfo);
13671bool OpenMPAtomicCompareCaptureChecker::checkStmt(
Stmt *S,
13672 ErrorInfoTy &ErrorInfo) {
13674 if (
auto *IS = dyn_cast<IfStmt>(S))
13675 return checkForm3(IS, ErrorInfo);
13677 auto *CS = dyn_cast<CompoundStmt>(S);
13679 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
13680 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->
getBeginLoc();
13681 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->
getSourceRange();
13684 if (CS->body_empty()) {
13685 ErrorInfo.Error = ErrorTy::NoStmt;
13686 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13687 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
13692 if (CS->size() == 1) {
13693 auto *IS = dyn_cast<IfStmt>(CS->body_front());
13695 ErrorInfo.Error = ErrorTy::NotIfStmt;
13696 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->
getBeginLoc();
13697 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13702 return checkForm3(IS, ErrorInfo);
13703 }
else if (CS->size() == 2) {
13704 auto *S1 = CS->body_front();
13705 auto *S2 = CS->body_back();
13707 Stmt *UpdateStmt =
nullptr;
13708 Stmt *CondUpdateStmt =
nullptr;
13709 Stmt *CondExprStmt =
nullptr;
13711 if (
auto *BO = dyn_cast<BinaryOperator>(S1)) {
13721 return checkForm45(CS, ErrorInfo);
13726 IsPostfixUpdate =
true;
13730 CondUpdateStmt = S2;
13739 CondUpdateStmt = S1;
13742 auto CheckCondUpdateStmt = [
this, &ErrorInfo](
Stmt *CUS) {
13743 auto *IS = dyn_cast<IfStmt>(CUS);
13745 ErrorInfo.Error = ErrorTy::NotIfStmt;
13746 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
13747 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
13751 return checkCondUpdateStmt(IS, ErrorInfo);
13755 auto CheckUpdateStmt = [
this, &ErrorInfo](
Stmt *US) {
13756 auto *BO = dyn_cast<BinaryOperator>(US);
13758 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13759 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
13760 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
13763 if (BO->getOpcode() != BO_Assign) {
13764 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13765 ErrorInfo.ErrorLoc = BO->getExprLoc();
13766 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13767 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13770 if (!checkIfTwoExprsAreSame(ContextRef, this->
X, BO->getRHS())) {
13771 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13772 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
13773 ErrorInfo.NoteLoc = this->
X->getExprLoc();
13774 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
13775 ErrorInfo.NoteRange = this->
X->getSourceRange();
13779 this->
V = BO->getLHS();
13784 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
13786 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
13788 if (!CheckUpdateStmt(UpdateStmt))
13791 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
13792 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->
getBeginLoc();
13793 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->
getSourceRange();
13797 return checkType(ErrorInfo);
13808 DSAStack->addAtomicDirectiveLoc(StartLoc);
13821 bool MutexClauseEncountered =
false;
13822 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
13824 switch (
C->getClauseKind()) {
13828 MutexClauseEncountered =
true;
13831 case OMPC_compare: {
13832 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
13833 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
13835 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
13838 AtomicKind =
C->getClauseKind();
13839 AtomicKindLoc =
C->getBeginLoc();
13840 if (!EncounteredAtomicKinds.insert(
C->getClauseKind()).second) {
13841 Diag(
C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
13843 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
13851 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
13852 Diag(
C->getBeginLoc(), diag::err_omp_atomic_no_compare)
13863 case OMPC_relaxed: {
13864 if (MemOrderKind != OMPC_unknown) {
13865 Diag(
C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
13866 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
13868 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
13871 MemOrderKind =
C->getClauseKind();
13872 MemOrderLoc =
C->getBeginLoc();
13880 llvm_unreachable(
"unknown clause is encountered");
13883 bool IsCompareCapture =
false;
13884 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
13885 EncounteredAtomicKinds.contains(OMPC_capture)) {
13886 IsCompareCapture =
true;
13887 AtomicKind = OMPC_compare;
13896 if ((AtomicKind == OMPC_read &&
13897 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
13898 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
13899 AtomicKind == OMPC_unknown) &&
13900 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
13902 if (AtomicKind == OMPC_unknown)
13904 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
13906 << (AtomicKind == OMPC_unknown ? 1 : 0)
13908 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
13912 Stmt *Body = AStmt;
13913 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Body))
13914 Body = EWC->getSubExpr();
13919 Expr *UE =
nullptr;
13921 Expr *CE =
nullptr;
13923 bool IsXLHSInRHSPart =
false;
13924 bool IsPostfixUpdate =
false;
13925 bool IsFailOnly =
false;
13948 if (AtomicKind == OMPC_read) {
13955 } ErrorFound = NoError;
13960 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13961 const auto *AtomicBinOp =
13962 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13963 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
13966 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
13967 (
V->isInstantiationDependent() ||
V->getType()->isScalarType())) {
13968 if (!
X->isLValue() || !
V->isLValue()) {
13969 const Expr *NotLValueExpr =
X->isLValue() ?
V :
X;
13970 ErrorFound = NotAnLValue;
13976 }
else if (!
X->isInstantiationDependent() ||
13977 !
V->isInstantiationDependent()) {
13978 const Expr *NotScalarExpr =
13979 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
13982 ErrorFound = NotAScalarType;
13988 }
else if (!AtomicBody->isInstantiationDependent()) {
13989 ErrorFound = NotAnAssignmentOp;
13990 ErrorLoc = AtomicBody->getExprLoc();
13991 ErrorRange = AtomicBody->getSourceRange();
13993 : AtomicBody->getExprLoc();
13995 : AtomicBody->getSourceRange();
13998 ErrorFound = NotAnExpression;
14000 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
14002 if (ErrorFound != NoError) {
14003 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
14005 Diag(NoteLoc, diag::note_omp_atomic_read_write)
14006 << ErrorFound << NoteRange;
14009 if (
SemaRef.CurContext->isDependentContext())
14011 }
else if (AtomicKind == OMPC_write) {
14018 } ErrorFound = NoError;
14023 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
14024 const auto *AtomicBinOp =
14025 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
14026 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
14028 E = AtomicBinOp->
getRHS();
14029 if ((
X->isInstantiationDependent() ||
X->getType()->isScalarType()) &&
14031 if (!
X->isLValue()) {
14032 ErrorFound = NotAnLValue;
14035 NoteLoc =
X->getExprLoc();
14036 NoteRange =
X->getSourceRange();
14038 }
else if (!
X->isInstantiationDependent() ||
14040 const Expr *NotScalarExpr =
14041 (
X->isInstantiationDependent() ||
X->getType()->isScalarType())
14044 ErrorFound = NotAScalarType;
14050 }
else if (!AtomicBody->isInstantiationDependent()) {
14051 ErrorFound = NotAnAssignmentOp;
14052 ErrorLoc = AtomicBody->getExprLoc();
14053 ErrorRange = AtomicBody->getSourceRange();
14055 : AtomicBody->getExprLoc();
14057 : AtomicBody->getSourceRange();
14060 ErrorFound = NotAnExpression;
14062 NoteRange = ErrorRange =
SourceRange(NoteLoc, NoteLoc);
14064 if (ErrorFound != NoError) {
14065 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
14067 Diag(NoteLoc, diag::note_omp_atomic_read_write)
14068 << ErrorFound << NoteRange;
14071 if (
SemaRef.CurContext->isDependentContext())
14073 }
else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
14082 OpenMPAtomicUpdateChecker Checker(
SemaRef);
14083 if (Checker.checkStatement(
14085 (AtomicKind == OMPC_update)
14086 ? diag::err_omp_atomic_update_not_expression_statement
14087 : diag::err_omp_atomic_not_expression_statement,
14088 diag::note_omp_atomic_update))
14090 if (!
SemaRef.CurContext->isDependentContext()) {
14091 E = Checker.getExpr();
14092 X = Checker.getX();
14093 UE = Checker.getUpdateExpr();
14094 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
14096 }
else if (AtomicKind == OMPC_capture) {
14099 NotACompoundStatement,
14100 NotTwoSubstatements,
14101 NotASpecificExpression,
14103 } ErrorFound = NoError;
14106 if (
const auto *AtomicBody = dyn_cast<Expr>(Body)) {
14115 const auto *AtomicBinOp =
14116 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
14117 if (AtomicBinOp && AtomicBinOp->
getOpcode() == BO_Assign) {
14120 OpenMPAtomicUpdateChecker Checker(
SemaRef);
14121 if (Checker.checkStatement(
14122 Body, diag::err_omp_atomic_capture_not_expression_statement,
14123 diag::note_omp_atomic_update))
14125 E = Checker.getExpr();
14126 X = Checker.getX();
14127 UE = Checker.getUpdateExpr();
14128 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
14129 IsPostfixUpdate = Checker.isPostfixUpdate();
14130 }
else if (!AtomicBody->isInstantiationDependent()) {
14131 ErrorLoc = AtomicBody->getExprLoc();
14132 ErrorRange = AtomicBody->getSourceRange();
14134 : AtomicBody->getExprLoc();
14136 : AtomicBody->getSourceRange();
14137 ErrorFound = NotAnAssignmentOp;
14139 if (ErrorFound != NoError) {
14140 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
14142 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
14145 if (
SemaRef.CurContext->isDependentContext())
14146 UE =
V = E =
X =
nullptr;
14164 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
14166 if (CS->size() == 2) {
14168 Stmt *Second = CS->body_back();
14169 if (
auto *EWC = dyn_cast<ExprWithCleanups>(
First))
14170 First = EWC->getSubExpr()->IgnoreParenImpCasts();
14171 if (
auto *EWC = dyn_cast<ExprWithCleanups>(Second))
14172 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
14174 OpenMPAtomicUpdateChecker Checker(
SemaRef);
14175 bool IsUpdateExprFound = !Checker.checkStatement(Second);
14177 if (IsUpdateExprFound) {
14178 BinOp = dyn_cast<BinaryOperator>(
First);
14179 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
14181 if (IsUpdateExprFound && !
SemaRef.CurContext->isDependentContext()) {
14191 llvm::FoldingSetNodeID XId, PossibleXId;
14192 Checker.getX()->Profile(XId, Context,
true);
14193 PossibleX->
Profile(PossibleXId, Context,
true);
14194 IsUpdateExprFound = XId == PossibleXId;
14195 if (IsUpdateExprFound) {
14197 X = Checker.getX();
14198 E = Checker.getExpr();
14199 UE = Checker.getUpdateExpr();
14200 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
14201 IsPostfixUpdate =
true;
14204 if (!IsUpdateExprFound) {
14205 IsUpdateExprFound = !Checker.checkStatement(
First);
14207 if (IsUpdateExprFound) {
14208 BinOp = dyn_cast<BinaryOperator>(Second);
14209 IsUpdateExprFound = BinOp && BinOp->
getOpcode() == BO_Assign;
14211 if (IsUpdateExprFound &&
14212 !
SemaRef.CurContext->isDependentContext()) {
14222 llvm::FoldingSetNodeID XId, PossibleXId;
14223 Checker.getX()->Profile(XId, Context,
true);
14224 PossibleX->
Profile(PossibleXId, Context,
true);
14225 IsUpdateExprFound = XId == PossibleXId;
14226 if (IsUpdateExprFound) {
14228 X = Checker.getX();
14229 E = Checker.getExpr();
14230 UE = Checker.getUpdateExpr();
14231 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
14232 IsPostfixUpdate =
false;
14236 if (!IsUpdateExprFound) {
14238 auto *FirstExpr = dyn_cast<Expr>(
First);
14239 auto *SecondExpr = dyn_cast<Expr>(Second);
14240 if (!FirstExpr || !SecondExpr ||
14241 !(FirstExpr->isInstantiationDependent() ||
14242 SecondExpr->isInstantiationDependent())) {
14243 auto *FirstBinOp = dyn_cast<BinaryOperator>(
First);
14244 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
14245 ErrorFound = NotAnAssignmentOp;
14246 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
14247 :
First->getBeginLoc();
14248 NoteRange = ErrorRange = FirstBinOp
14249 ? FirstBinOp->getSourceRange()
14252 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
14253 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
14254 ErrorFound = NotAnAssignmentOp;
14255 NoteLoc = ErrorLoc = SecondBinOp
14256 ? SecondBinOp->getOperatorLoc()
14258 NoteRange = ErrorRange =
14259 SecondBinOp ? SecondBinOp->getSourceRange()
14262 Expr *PossibleXRHSInFirst =
14264 Expr *PossibleXLHSInSecond =
14266 llvm::FoldingSetNodeID X1Id, X2Id;
14267 PossibleXRHSInFirst->
Profile(X1Id, Context,
14269 PossibleXLHSInSecond->
Profile(X2Id, Context,
14271 IsUpdateExprFound = X1Id == X2Id;
14272 if (IsUpdateExprFound) {
14273 V = FirstBinOp->getLHS();
14274 X = SecondBinOp->getLHS();
14275 E = SecondBinOp->getRHS();
14277 IsXLHSInRHSPart =
false;
14278 IsPostfixUpdate =
true;
14280 ErrorFound = NotASpecificExpression;
14281 ErrorLoc = FirstBinOp->getExprLoc();
14282 ErrorRange = FirstBinOp->getSourceRange();
14283 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
14284 NoteRange = SecondBinOp->getRHS()->getSourceRange();
14292 NoteRange = ErrorRange =
14294 ErrorFound = NotTwoSubstatements;
14298 NoteRange = ErrorRange =
14300 ErrorFound = NotACompoundStatement;
14303 if (ErrorFound != NoError) {
14304 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
14306 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
14309 if (
SemaRef.CurContext->isDependentContext())
14310 UE =
V = E =
X =
nullptr;
14311 }
else if (AtomicKind == OMPC_compare) {
14312 if (IsCompareCapture) {
14313 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
14314 OpenMPAtomicCompareCaptureChecker Checker(
SemaRef);
14315 if (!Checker.checkStmt(Body, ErrorInfo)) {
14316 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
14317 << ErrorInfo.ErrorRange;
14318 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
14319 << ErrorInfo.Error << ErrorInfo.NoteRange;
14322 X = Checker.getX();
14323 E = Checker.getE();
14324 D = Checker.getD();
14325 CE = Checker.getCond();
14326 V = Checker.getV();
14327 R = Checker.getR();
14329 IsXLHSInRHSPart = Checker.isXBinopExpr();
14330 IsFailOnly = Checker.isFailOnly();
14331 IsPostfixUpdate = Checker.isPostfixUpdate();
14333 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
14334 OpenMPAtomicCompareChecker Checker(
SemaRef);
14335 if (!Checker.checkStmt(Body, ErrorInfo)) {
14336 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
14337 << ErrorInfo.ErrorRange;
14338 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
14339 << ErrorInfo.Error << ErrorInfo.NoteRange;
14342 X = Checker.getX();
14343 E = Checker.getE();
14344 D = Checker.getD();
14345 CE = Checker.getCond();
14351 auto *It = find_if(Clauses, [](
OMPClause *
C) {
14352 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
14354 if (It != Clauses.end()) {
14355 auto *Cond = dyn_cast<BinaryOperator>(CE);
14356 if (Cond->getOpcode() != BO_EQ) {
14357 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
14359 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
14360 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->
getSourceRange();
14362 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
14363 << ErrorInfo.ErrorRange;
14368 IsXLHSInRHSPart = Checker.isXBinopExpr();
14372 SemaRef.setFunctionHasBranchProtectedScope();
14375 Context, StartLoc, EndLoc, Clauses, AStmt,
14376 {
X,
V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
14402 if (
DSAStack->hasInnerTeamsRegion()) {
14404 bool OMPTeamsFound =
true;
14405 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
14406 auto I = CS->body_begin();
14407 while (I != CS->body_end()) {
14408 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
14410 if (!IsTeams || I != CS->body_begin()) {
14411 OMPTeamsFound =
false;
14412 if (IsTeams && I != CS->body_begin()) {
14421 assert(I != CS->body_end() &&
"Not found statement");
14424 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
14427 if (!OMPTeamsFound) {
14428 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
14430 diag::note_omp_nested_teams_construct_here);
14484 OMPLoopBasedDirective::HelperExprs B;
14487 unsigned NestedLoopCount =
14490 VarsWithImplicitDSA, B);
14491 if (NestedLoopCount == 0)
14498 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14505 return llvm::any_of(
14506 Clauses, [K](
const OMPClause *
C) {
return C->getClauseKind() == K; });
14509template <
typename... Params>
14511 const Params... ClauseTypes) {
14518 if (
auto *TC = dyn_cast<OMPToClause>(
C))
14519 return llvm::all_of(TC->all_decls(), [](
ValueDecl *VD) {
14520 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
14521 (VD->isExternallyVisible() &&
14522 VD->getVisibility() != HiddenVisibility);
14524 else if (
auto *FC = dyn_cast<OMPFromClause>(
C))
14525 return llvm::all_of(FC->all_decls(), [](
ValueDecl *VD) {
14526 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
14527 (VD->isExternallyVisible() &&
14528 VD->getVisibility() != HiddenVisibility);
14547 if (!
hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
14549 !
hasClauses(Clauses, OMPC_use_device_addr))) {
14552 Expected =
"'map' or 'use_device_ptr'";
14554 Expected =
"'map', 'use_device_ptr', or 'use_device_addr'";
14556 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
14557 <<
Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
14561 SemaRef.setFunctionHasBranchProtectedScope();
14579 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
14581 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
14601 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
14602 <<
"'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
14618 if (!
hasClauses(Clauses, OMPC_to, OMPC_from)) {
14619 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
14624 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
14647 Diag(StartLoc, diag::warn_hip_omp_target_directives);
14651 DSAStack->setParentTeamsRegionLoc(StartLoc);
14660 if (
DSAStack->isParentNowaitRegion()) {
14661 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
14664 if (
DSAStack->isParentOrderedRegion()) {
14665 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
14669 EndLoc, CancelRegion);
14675 if (
DSAStack->isParentNowaitRegion()) {
14676 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
14679 if (
DSAStack->isParentOrderedRegion()) {
14680 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
14683 DSAStack->setParentCancelRegion(
true);
14690 const OMPClause *ReductionClause =
nullptr;
14691 const OMPClause *NogroupClause =
nullptr;
14693 if (
C->getClauseKind() == OMPC_reduction) {
14694 ReductionClause =
C;
14699 if (
C->getClauseKind() == OMPC_nogroup) {
14701 if (ReductionClause)
14706 if (ReductionClause && NogroupClause) {
14707 S.
Diag(ReductionClause->
getBeginLoc(), diag::err_omp_reduction_with_nogroup)
14722 OMPLoopBasedDirective::HelperExprs B;
14725 unsigned NestedLoopCount =
14728 *
DSAStack, VarsWithImplicitDSA, B);
14729 if (NestedLoopCount == 0)
14732 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14733 "omp for loop exprs were not built");
14739 {OMPC_grainsize, OMPC_num_tasks}))
14747 SemaRef.setFunctionHasBranchProtectedScope();
14749 NestedLoopCount, Clauses, AStmt, B,
14763 OMPLoopBasedDirective::HelperExprs B;
14766 unsigned NestedLoopCount =
14769 VarsWithImplicitDSA, B);
14770 if (NestedLoopCount == 0)
14780 {OMPC_grainsize, OMPC_num_tasks}))
14791 NestedLoopCount, Clauses, AStmt, B);
14801 OMPLoopBasedDirective::HelperExprs B;
14804 unsigned NestedLoopCount =
14807 *
DSAStack, VarsWithImplicitDSA, B);
14808 if (NestedLoopCount == 0)
14811 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14812 "omp for loop exprs were not built");
14818 {OMPC_grainsize, OMPC_num_tasks}))
14826 SemaRef.setFunctionHasBranchProtectedScope();
14828 NestedLoopCount, Clauses, AStmt, B,
14839 OMPLoopBasedDirective::HelperExprs B;
14842 unsigned NestedLoopCount =
14845 *
DSAStack, VarsWithImplicitDSA, B);
14846 if (NestedLoopCount == 0)
14849 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14850 "omp for loop exprs were not built");
14856 {OMPC_grainsize, OMPC_num_tasks}))
14864 SemaRef.setFunctionHasBranchProtectedScope();
14866 NestedLoopCount, Clauses, AStmt, B,
14880 OMPLoopBasedDirective::HelperExprs B;
14883 unsigned NestedLoopCount =
14886 VarsWithImplicitDSA, B);
14887 if (NestedLoopCount == 0)
14897 {OMPC_grainsize, OMPC_num_tasks}))
14908 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14921 OMPLoopBasedDirective::HelperExprs B;
14924 unsigned NestedLoopCount =
14927 VarsWithImplicitDSA, B);
14928 if (NestedLoopCount == 0)
14938 {OMPC_grainsize, OMPC_num_tasks}))
14949 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14961 OMPLoopBasedDirective::HelperExprs B;
14967 VarsWithImplicitDSA, B);
14968 if (NestedLoopCount == 0)
14971 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14972 "omp for loop exprs were not built");
14978 {OMPC_grainsize, OMPC_num_tasks}))
14987 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15000 OMPLoopBasedDirective::HelperExprs B;
15006 VarsWithImplicitDSA, B);
15007 if (NestedLoopCount == 0)
15010 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15011 "omp for loop exprs were not built");
15017 {OMPC_grainsize, OMPC_num_tasks}))
15026 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15037 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
15039 OMPLoopBasedDirective::HelperExprs B;
15045 VarsWithImplicitDSA, B);
15046 if (NestedLoopCount == 0)
15056 {OMPC_grainsize, OMPC_num_tasks}))
15067 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15077 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
15079 OMPLoopBasedDirective::HelperExprs B;
15085 VarsWithImplicitDSA, B);
15086 if (NestedLoopCount == 0)
15096 {OMPC_grainsize, OMPC_num_tasks}))
15107 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15117 OMPLoopBasedDirective::HelperExprs B;
15120 unsigned NestedLoopCount =
15124 if (NestedLoopCount == 0)
15127 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15128 "omp for loop exprs were not built");
15130 SemaRef.setFunctionHasBranchProtectedScope();
15132 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15133 return DistributeDirective;
15145 OMPLoopBasedDirective::HelperExprs B;
15151 VarsWithImplicitDSA, B);
15152 if (NestedLoopCount == 0)
15155 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15156 "omp for loop exprs were not built");
15159 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15170 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
15172 OMPLoopBasedDirective::HelperExprs B;
15178 VarsWithImplicitDSA, B);
15179 if (NestedLoopCount == 0)
15189 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15201 OMPLoopBasedDirective::HelperExprs B;
15204 unsigned NestedLoopCount =
15208 if (NestedLoopCount == 0)
15218 NestedLoopCount, Clauses, AStmt, B);
15231 SemaRef, OMPD_target_parallel_for_simd, Clauses))
15240 OMPLoopBasedDirective::HelperExprs B;
15246 VarsWithImplicitDSA, B);
15247 if (NestedLoopCount == 0)
15257 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15277 OMPLoopBasedDirective::HelperExprs B;
15280 unsigned NestedLoopCount =
15283 VarsWithImplicitDSA, B);
15284 if (NestedLoopCount == 0)
15294 NestedLoopCount, Clauses, AStmt, B);
15313 OMPLoopBasedDirective::HelperExprs B;
15316 unsigned NestedLoopCount =
15320 if (NestedLoopCount == 0)
15323 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15324 "omp teams distribute loop exprs were not built");
15326 DSAStack->setParentTeamsRegionLoc(StartLoc);
15329 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15347 OMPLoopBasedDirective::HelperExprs B;
15353 VarsWithImplicitDSA, B);
15354 if (NestedLoopCount == 0)
15363 DSAStack->setParentTeamsRegionLoc(StartLoc);
15366 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15379 SemaRef, OMPD_teams_distribute_parallel_for_simd, Clauses))
15383 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
15385 OMPLoopBasedDirective::HelperExprs B;
15391 VarsWithImplicitDSA, B);
15392 if (NestedLoopCount == 0)
15401 DSAStack->setParentTeamsRegionLoc(StartLoc);
15404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15417 SemaRef, OMPD_teams_distribute_parallel_for, Clauses))
15421 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
15423 OMPLoopBasedDirective::HelperExprs B;
15429 VarsWithImplicitDSA, B);
15431 if (NestedLoopCount == 0)
15434 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15435 "omp for loop exprs were not built");
15437 DSAStack->setParentTeamsRegionLoc(StartLoc);
15440 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15476 SemaRef, OMPD_target_teams_distribute, Clauses))
15485 OMPLoopBasedDirective::HelperExprs B;
15491 VarsWithImplicitDSA, B);
15492 if (NestedLoopCount == 0)
15495 assert((
SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15496 "omp target teams distribute loop exprs were not built");
15499 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15512 SemaRef, OMPD_target_teams_distribute_parallel_for, Clauses))
15519 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
15521 OMPLoopBasedDirective::HelperExprs B;
15527 VarsWithImplicitDSA, B);
15528 if (NestedLoopCount == 0)
15535 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15549 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, Clauses))
15556 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
15558 OMPLoopBasedDirective::HelperExprs B;
15561 unsigned NestedLoopCount =
15566 if (NestedLoopCount == 0)
15576 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15589 SemaRef, OMPD_target_teams_distribute_simd, Clauses))
15596 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
15598 OMPLoopBasedDirective::HelperExprs B;
15604 VarsWithImplicitDSA, B);
15605 if (NestedLoopCount == 0)
15615 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15624#define STMT(CLASS, PARENT)
15625#define ABSTRACT_STMT(CLASS)
15626#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
15627 case Stmt::CLASS##Class: \
15628 appendFlattenedStmtList(PreInits, \
15629 static_cast<const CLASS *>(Dir)->getPreInits()); \
15631#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
15632 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
15633#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
15634 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
15635#include "clang/AST/StmtNodes.inc"
15636#undef COMMON_OMP_LOOP_TRANSFORMATION
15638 llvm_unreachable(
"Not a loop transformation");
15642bool SemaOpenMP::checkTransformableLoopNest(
15648 NestedFinals->assign(NumLoops,
nullptr);
15649 OriginalInits.emplace_back();
15654 Kind == OMPD_tile ||
Kind == OMPD_stripe;
15655 bool Result = OMPLoopBasedDirective::doForAllLoops(
15657 [
this, &LoopHelpers, &Body, &OriginalInits,
15658 Kind](
unsigned Cnt, Stmt *CurStmt, Stmt *HintWrapper) {
15663 SemaRef.Diag(CurStmt->getBeginLoc(),
15664 diag::err_omp_collapse_stacked_tile)
15669 unsigned SingleNumLoops =
15671 TmpDSA, LoopHelpers[Cnt]);
15672 if (SingleNumLoops == 0)
15674 assert(SingleNumLoops == 1 &&
"Expect single loop iteration space");
15675 if (
auto *For = dyn_cast<ForStmt>(CurStmt)) {
15676 OriginalInits.back().push_back(For->getInit());
15677 Body = For->getBody();
15680 "Expected canonical for or range-based for loops.");
15682 OriginalInits.back().push_back(CXXFor->getBeginStmt());
15683 Body = CXXFor->getBody();
15685 OriginalInits.emplace_back();
15689 NestedFinals](OMPLoopTransformationDirective *Transform) {
15692 if (
Stmt *Finals = Transform->getFinals()) {
15693 assert(!(*NestedFinals)[OriginalInits.size() - 1] &&
15694 "Expected one nested transformation per loop");
15695 (*NestedFinals)[OriginalInits.size() - 1] = Finals;
15699 assert(OriginalInits.back().empty() &&
"No preinit after innermost loop");
15700 OriginalInits.pop_back();
15738 unsigned NestedLoopCount = 0;
15785bool SemaOpenMP::analyzeLoopSequence(
Stmt *LoopSeqStmt,
15786 LoopSequenceAnalysis &SeqAnalysis,
15789 bool IsGeneratedSequence) {
15793 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
15794 if (
auto *For = dyn_cast<ForStmt>(LoopStmt)) {
15795 Analysis.OriginalInits.push_back(For->getInit());
15796 Analysis.TheForStmt = For;
15799 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
15800 Analysis.TheForStmt = CXXFor;
15807 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
15809 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
15810 unsigned NumGeneratedTopLevelLoops =
15811 LoopTransform->getNumGeneratedTopLevelLoops();
15814 if (!TransformedStmt) {
15815 if (NumGeneratedTopLevelLoops > 0) {
15816 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
15820 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
15821 << 0 << getOpenMPDirectiveName(Kind);
15826 if (!NumGeneratedTopLevelLoops) {
15827 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
15828 << 0 << getOpenMPDirectiveName(Kind);
15832 if (NumGeneratedTopLevelLoops > 1) {
15839 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
15840 if (!analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind,
15844 if (Stmt *Finals = LoopTransform->getFinals()) {
15845 assert(!SeqAnalysis.Loops.back().TransformFinals &&
15846 "Generated loop already has Finals");
15847 SeqAnalysis.Loops.back().TransformFinals = Finals;
15853 LoopAnalysis &NewTransformedSingleLoop =
15854 SeqAnalysis.Loops.emplace_back(Child);
15857 NewTransformedSingleLoop.HelperExprs);
15862 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
15863 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
15864 NewTransformedSingleLoop.TransformFinals = LoopTransform->getFinals();
15866 SeqAnalysis.LoopSeqSize++;
15871 auto AnalyzeRegularLoop = [&](Stmt *Child) {
15872 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
15873 unsigned IsCanonical =
15875 TmpDSA, NewRegularLoop.HelperExprs);
15880 StoreLoopStatements(NewRegularLoop, Child);
15881 NestedLoopCounterVisitor NLCV;
15887 for (Stmt *Child : LoopSeqStmt->
children()) {
15894 if (IsGeneratedSequence) {
15895 auto *CS = dyn_cast<CompoundStmt>(Child);
15896 if (CS && CS->size() == 2 &&
15897 LoopAnalysis::isRegularLoop(CS->body_front()) &&
15898 !LoopAnalysis::isRegularLoop(CS->body_back())) {
15899 if (!AnalyzeRegularLoop(CS->body_front()))
15901 SeqAnalysis.Loops.back().TransformFinals = CS->body_back();
15902 SeqAnalysis.LoopSeqSize++;
15907 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
15908 Child = Child->IgnoreContainers();
15915 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind,
15916 IsGeneratedSequence))
15923 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
15924 if (LoopAnalysis::isLoopTransformation(Child)) {
15925 if (!AnalyzeLoopGeneration(Child))
15929 if (!AnalyzeRegularLoop(Child))
15931 SeqAnalysis.LoopSeqSize++;
15935 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
15936 << 0 << getOpenMPDirectiveName(Kind);
15943bool SemaOpenMP::checkTransformableLoopSequence(
15968 << getOpenMPDirectiveName(Kind);
15973 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
15977 if (!SeqAnalysis.LoopSeqSize) {
15979 << getOpenMPDirectiveName(Kind);
15987 OMPLoopBasedDirective::HelperExprs &LoopHelper,
15993 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
15994 Stmt *RangeInit = CXXRangeFor->getInit();
15996 PreInits.push_back(RangeInit);
15998 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
16003 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
16009 llvm::append_range(PreInits, OriginalInit);
16012 if (
auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
16013 PreInits.push_back(
new (Context)
DeclStmt(
16014 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
16018 for (
Expr *CounterRef : LoopHelper.Counters) {
16021 PreInits.push_back(
new (Context)
DeclStmt(
16030 size_t NumLoops = LoopStmts.size();
16031 OMPLoopBasedDirective::doForAllLoops(
16032 AStmt,
false, NumLoops,
16033 [LoopStmts](
unsigned Cnt,
Stmt *CurStmt) {
16034 assert(!LoopStmts[Cnt] &&
"Loop statement must not yet be assigned");
16035 LoopStmts[Cnt] = CurStmt;
16039 assert(!is_contained(LoopStmts,
nullptr) &&
16040 "Expecting a loop statement for each affected loop");
16052 llvm::append_range(BodyParts,
16053 OMPLoopBasedDirective::getStmtsBeforeNestedLoop(Body));
16067 const auto *DRE = dyn_cast<DeclRefExpr>(Counter);
16068 const auto *VD = DRE ? dyn_cast<VarDecl>(DRE->
getDecl()) :
nullptr;
16073 const auto *For = dyn_cast<ForStmt>(LoopStmt);
16074 const auto *
Init = For ? dyn_cast_or_null<DeclStmt>(For->getInit()) :
nullptr;
16075 return Init && llvm::is_contained(
Init->decls(), VD);
16083 for (
const auto &
Loop : llvm::reverse(Loops))
16114 assert(LoopStmts.size() == LoopHelpers.size() &&
16115 "Expected one loop statement per loop");
16116 auto GetFinals = [](
const OMPLoopBasedDirective::HelperExprs &Helper,
16117 const Stmt *LoopStmt) {
16119 for (
auto [Counter, Final] :
16120 llvm::zip_equal(Helper.Counters, Helper.Finals)) {
16128 Finals.push_back(Final);
16137 auto GetNestedFinals = [&](
size_t I) ->
Stmt * {
16138 return I < NestedFinals.size() ? NestedFinals[I] :
nullptr;
16142 Stmt *Nested =
nullptr;
16143 for (
size_t I = LoopHelpers.size(); I-- > 0;) {
16145 if (
Stmt *F = GetNestedFinals(I))
16148 Body.push_back(Nested);
16152 Body.size() == 1 ? Body.front()
16153 : MakeCompound(Body));
16165 const auto *SizesClause =
16166 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
16167 if (!SizesClause ||
16168 llvm::any_of(SizesClause->getSizesRefs(), [](
Expr *E) { return !E; }))
16170 unsigned NumLoops = SizesClause->getNumSizes();
16178 Stmt *Body =
nullptr;
16181 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
16182 OriginalInits, &NestedFinals))
16186 if (
SemaRef.CurContext->isDependentContext())
16188 NumLoops, AStmt,
nullptr,
nullptr,
nullptr);
16190 assert(LoopHelpers.size() == NumLoops &&
16191 "Expecting loop iteration space dimensionality to match number of "
16193 assert(OriginalInits.size() == NumLoops &&
16194 "Expecting loop iteration space dimensionality to match number of "
16202 CaptureVars CopyTransformer(
SemaRef);
16207 FloorIndVars.resize(NumLoops);
16208 TileIndVars.resize(NumLoops);
16209 for (
unsigned I = 0; I < NumLoops; ++I) {
16210 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16212 assert(LoopHelper.Counters.size() == 1 &&
16213 "Expect single-dimensional loop iteration space");
16215 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16221 std::string FloorCntName =
16222 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
16225 FloorIndVars[I] = FloorCntDecl;
16230 std::string TileCntName =
16231 (Twine(
".tile_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
16237 TileCntDecl->setDeclName(
16238 &
SemaRef.PP.getIdentifierTable().get(TileCntName));
16239 TileIndVars[I] = TileCntDecl;
16248 Stmt *Inner = Body;
16250 auto MakeDimTileSize = [&
SemaRef = this->SemaRef, &CopyTransformer, &Context,
16251 SizesClause, CurScope](
int I) ->
Expr * {
16252 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
16258 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
16277 unsigned DimWidth = Context.getIntWidth(DimTy);
16279 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
16283 CurScope, {}, BO_LE,
16287 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
16316 for (
int I = NumLoops - 1; I >= 0; --I) {
16317 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16318 Expr *NumIterations = LoopHelper.NumIterations;
16321 Stmt *LoopStmt = LoopStmts[I];
16326 auto MakeTileIVRef = [&
SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
16329 OrigCntVar->getExprLoc());
16333 SemaRef.AddInitializerToDecl(
16336 .DefaultLvalueConversion(
16340 Decl *CounterDecl = TileIndVars[I];
16343 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16349 Expr *DimTileSize = MakeDimTileSize(I);
16353 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
16359 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16360 NumIterations, EndOfTile.
get());
16364 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
16365 IsPartialTile.
get(), NumIterations, EndOfTile.
get());
16366 if (!MinTileAndIterSpace.
isUsable())
16369 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16370 MakeTileIVRef(), MinTileAndIterSpace.
get());
16376 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
16382 Expr *RectDimTileSize = MakeDimTileSize(I);
16383 if (!RectDimTileSize)
16386 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
16392 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16393 MakeTileIVRef(), RectEndOfTile.
get());
16394 Expr *TileSizeExpr = MakeDimTileSize(I);
16408 bool NoPartialTile =
false;
16412 llvm::APSInt TS = TileSizeVal.
Val.
getInt();
16413 llvm::APSInt N = NumIterationsVal.
Val.
getInt();
16414 unsigned Width = std::max(TS.getBitWidth(), N.getBitWidth());
16415 TS = TS.extend(Width);
16416 N = N.extend(Width);
16418 TS.isStrictlyPositive() && N.isStrictlyPositive() && N.urem(TS) == 0;
16422 if (!NoPartialTile) {
16423 Predicate =
SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
16424 BO_LT, MakeTileIVRef(), NumIterations);
16446 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
16447 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
16448 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16449 if (
static_cast<unsigned>(I) + 1 < NumLoops)
16451 BodyParts.push_back(Inner);
16454 Inner =
new (Context)
16457 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16460 auto *Hint = OMPInvariantPredicateBoundAttr::CreateImplicit(
16461 Context, RectCond.
get(), TileSize.
get(),
16462 Predicate.
isUsable() ? Predicate.
get() :
nullptr,
16469 for (
int I = NumLoops - 1; I >= 0; --I) {
16470 auto &LoopHelper = LoopHelpers[I];
16471 Expr *NumIterations = LoopHelper.NumIterations;
16476 SemaRef.AddInitializerToDecl(
16478 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
16480 Decl *CounterDecl = FloorIndVars[I];
16489 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16496 Expr *DimTileSize = MakeDimTileSize(I);
16500 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
16506 Inner =
new (Context)
16509 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16513 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, Inner,
16525 const auto *SizesClause =
16526 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
16527 if (!SizesClause ||
16528 llvm::any_of(SizesClause->getSizesRefs(), [](
const Expr *SizeExpr) {
16529 return !SizeExpr || SizeExpr->containsErrors();
16532 unsigned NumLoops = SizesClause->getNumSizes();
16540 Stmt *Body =
nullptr;
16543 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
16544 Body, OriginalInits, &NestedFinals))
16548 if (
SemaRef.CurContext->isDependentContext())
16550 NumLoops, AStmt,
nullptr,
nullptr,
16553 assert(LoopHelpers.size() == NumLoops &&
16554 "Expecting loop iteration space dimensionality to match number of "
16556 assert(OriginalInits.size() == NumLoops &&
16557 "Expecting loop iteration space dimensionality to match number of "
16565 CaptureVars CopyTransformer(
SemaRef);
16570 FloorIndVars.resize(NumLoops);
16571 StripeIndVars.resize(NumLoops);
16572 for (
unsigned I : llvm::seq<unsigned>(NumLoops)) {
16573 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16575 assert(LoopHelper.Counters.size() == 1 &&
16576 "Expect single-dimensional loop iteration space");
16578 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16584 std::string FloorCntName =
16585 (Twine(
".floor_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
16588 FloorIndVars[I] = FloorCntDecl;
16593 std::string StripeCntName =
16594 (Twine(
".stripe_") + llvm::utostr(I) +
".iv." + OrigVarName).str();
16600 StripeCntDecl->setDeclName(
16601 &
SemaRef.PP.getIdentifierTable().get(StripeCntName));
16602 StripeIndVars[I] = StripeCntDecl;
16611 Stmt *Inner = Body;
16613 auto MakeDimStripeSize = [&](
int I) ->
Expr * {
16614 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
16616 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
16635 unsigned DimWidth = Context.getIntWidth(DimTy);
16637 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
16641 CurScope, {}, BO_LE,
16645 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
16651 for (
int I = NumLoops - 1; I >= 0; --I) {
16652 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16653 Expr *NumIterations = LoopHelper.NumIterations;
16656 Stmt *LoopStmt = LoopStmts[I];
16659 SemaRef.AddInitializerToDecl(
16662 .DefaultLvalueConversion(
16666 Decl *CounterDecl = StripeIndVars[I];
16669 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16676 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
16678 MakeDimStripeSize(I));
16682 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16683 NumIterations, EndOfStripe.
get());
16687 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
16688 IsPartialStripe.
get(), NumIterations, EndOfStripe.
get());
16689 if (!MinStripeAndIterSpace.
isUsable())
16692 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16694 MinStripeAndIterSpace.
get());
16700 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
16722 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
16723 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
16724 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16725 if (
static_cast<unsigned>(I) + 1 < NumLoops)
16727 BodyParts.push_back(Inner);
16730 Inner =
new (Context)
16733 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16737 for (
int I = NumLoops - 1; I >= 0; --I) {
16738 auto &LoopHelper = LoopHelpers[I];
16739 Expr *NumIterations = LoopHelper.NumIterations;
16744 SemaRef.AddInitializerToDecl(
16746 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
16748 Decl *CounterDecl = FloorIndVars[I];
16757 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16765 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
16767 MakeDimStripeSize(I));
16771 Inner =
new (Context)
16774 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16778 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, Inner,
16794 {OMPC_partial, OMPC_full}))
16798 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
16800 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
16801 assert(!(FullClause && PartialClause) &&
16802 "mutual exclusivity must have been checked before");
16804 constexpr unsigned NumLoops = 1;
16805 Stmt *Body =
nullptr;
16810 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
16811 Body, OriginalInits, &NestedFinals))
16814 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
16817 if (
SemaRef.CurContext->isDependentContext())
16819 NumGeneratedTopLevelLoops,
nullptr,
16822 assert(LoopHelpers.size() == NumLoops &&
16823 "Expecting a single-dimensional loop iteration space");
16824 assert(OriginalInits.size() == NumLoops &&
16825 "Expecting a single-dimensional loop iteration space");
16826 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16830 LoopHelper.NumIterations, OMPC_full,
false,
16833 Diag(AStmt->
getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
16835 <<
"#pragma omp unroll full";
16843 if (NumGeneratedTopLevelLoops == 0)
16845 NumGeneratedTopLevelLoops,
nullptr,
16891 Stmt *LoopStmt =
nullptr;
16896 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
16899 QualType IVTy = IterationVarRef->getType();
16900 assert(LoopHelper.Counters.size() == 1 &&
16901 "Expecting a single-dimensional loop iteration space");
16909 Factor = FactorVal->getIntegerConstantExpr(Context)->getLimitedValue();
16910 FactorLoc = FactorVal->getExprLoc();
16915 assert(Factor > 0 &&
"Expected positive unroll factor");
16916 auto MakeFactorExpr = [
this, Factor, IVTy, FactorLoc]() {
16928 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16929 std::string OuterIVName = (Twine(
".unrolled.iv.") + OrigVarName).str();
16930 std::string InnerIVName = (Twine(
".unroll_inner.iv.") + OrigVarName).str();
16935 auto MakeOuterRef = [
this, OuterIVDecl, IVTy, OrigVarLoc]() {
16941 auto *InnerIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
16942 InnerIVDecl->setDeclName(&
SemaRef.PP.getIdentifierTable().get(InnerIVName));
16943 auto MakeInnerRef = [
this, InnerIVDecl, IVTy, OrigVarLoc]() {
16949 CaptureVars CopyTransformer(
SemaRef);
16950 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
16952 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
16957 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.
get(),
16972 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
16973 MakeOuterRef(), MakeFactorExpr());
16977 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16978 MakeInnerRef(), EndOfTile.
get());
16982 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16983 MakeInnerRef(), MakeNumIterations());
16987 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
16988 InnerCond1.
get(), InnerCond2.
get());
16994 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
17000 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
17001 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
17002 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
17003 InnerBodyStmts.push_back(Body);
17007 ForStmt *InnerFor =
new (Context)
17008 ForStmt(Context, InnerInit.
get(), InnerCond.
get(),
nullptr,
17010 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17024 LoopHintAttr *UnrollHintAttr =
17025 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
17026 LoopHintAttr::Numeric, MakeFactorExpr());
17031 SemaRef.AddInitializerToDecl(
17033 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
17042 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
17043 MakeOuterRef(), MakeNumIterations());
17049 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
17050 MakeOuterRef(), MakeFactorExpr());
17055 ForStmt *OuterFor =
new (Context)
17056 ForStmt(Context, OuterInit.
get(), OuterConde.
get(),
nullptr,
17058 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17061 Context, StartLoc, EndLoc, Clauses, AStmt, NumGeneratedTopLevelLoops,
17076 constexpr unsigned NumLoops = 1;
17077 Stmt *Body =
nullptr;
17082 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
17083 Body, OriginalInits, &NestedFinals))
17088 if (
SemaRef.CurContext->isDependentContext())
17090 NumLoops,
nullptr,
nullptr,
nullptr);
17092 assert(LoopHelpers.size() == NumLoops &&
17093 "Expecting a single-dimensional loop iteration space");
17094 assert(OriginalInits.size() == NumLoops &&
17095 "Expecting a single-dimensional loop iteration space");
17096 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
17099 Stmt *LoopStmt =
nullptr;
17104 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
17107 QualType IVTy = IterationVarRef->getType();
17108 uint64_t IVWidth = Context.getTypeSize(IVTy);
17122 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
17124 ForwardIVName += OrigVarName;
17126 ReversedIVName += OrigVarName;
17159 CaptureVars CopyTransformer(
SemaRef);
17160 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() ->
Expr * {
17162 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
17168 auto MakeForwardRef = [&
SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
17175 auto *ReversedIVDecl =
cast<VarDecl>(IterationVarRef->getDecl());
17176 ReversedIVDecl->setDeclName(
17177 &
SemaRef.PP.getIdentifierTable().get(ReversedIVName));
17184 ForwardIVDecl->
getType(), OrigVarLoc);
17185 SemaRef.AddInitializerToDecl(ForwardIVDecl,
Zero,
false);
17188 if (!
Init.isUsable())
17196 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
17197 MakeForwardRef(), MakeNumIterations());
17206 UO_PreInc, MakeForwardRef());
17217 MakeNumIterations(), One);
17220 Minus =
SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.
get(),
17225 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
17228 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.
get(),
17233 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
17235 BodyStmts.push_back(InitReversed.
get());
17236 llvm::append_range(BodyStmts, LoopHelper.Updates);
17237 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
17238 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
17239 BodyStmts.push_back(Body);
17240 auto *ReversedBody =
17245 auto *ReversedFor =
new (Context)
17248 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17250 Context, StartLoc, EndLoc, AStmt, NumLoops, ReversedFor,
17270 const auto *CountsClause =
17271 OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
17276 constexpr unsigned NumLoops = 1;
17277 Stmt *Body =
nullptr;
17282 if (!checkTransformableLoopNest(OMPD_split, AStmt, NumLoops, LoopHelpers,
17283 Body, OriginalInits, &NestedFinals))
17288 if (
SemaRef.CurContext->isDependentContext())
17290 NumLoops, AStmt,
nullptr,
nullptr,
17293 assert(LoopHelpers.size() == NumLoops &&
17294 "Expecting a single-dimensional loop iteration space");
17295 assert(OriginalInits.size() == NumLoops &&
17296 "Expecting a single-dimensional loop iteration space");
17297 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
17300 Stmt *LoopStmt =
nullptr;
17305 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
17310 QualType IVTy = IterationVarRef->getType();
17311 uint64_t IVWidth = Context.getTypeSize(IVTy);
17319 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
17321 if (!CountsClause->hasOmpFill())
17323 unsigned FillIdx = *CountsClause->getOmpFillIndex();
17325 unsigned NumItems = CountsClause->getNumCounts();
17328 for (
unsigned I = 0; I < NumItems; ++I) {
17331 Expr *CountExpr = Refs[I];
17334 NumLoops, AStmt,
nullptr,
nullptr,
17336 std::optional<llvm::APSInt> OptVal =
17338 if (!OptVal || OptVal->isNegative())
17340 NumLoops, AStmt,
nullptr,
nullptr,
17342 CountValues[I] = OptVal->getLimitedValue();
17345 Expr *NumIterExpr = LoopHelper.NumIterations;
17347 uint64_t RightSum = 0;
17348 for (
unsigned I = FillIdx + 1; I < NumItems; ++I)
17349 RightSum += CountValues[I];
17351 auto MakeIntLit = [&](uint64_t Val) {
17356 size_t NumSegments = NumItems;
17359 auto *IterVarDecl =
cast<VarDecl>(IterationVarRef->getDecl());
17361 IterationVarRef->getBeginLoc(),
17362 IterationVarRef->getEndLoc()));
17364 uint64_t LeftAccum = 0;
17365 uint64_t RightRemaining = RightSum;
17367 for (
size_t Seg = 0; Seg < NumSegments; ++Seg) {
17368 Expr *StartExpr =
nullptr;
17369 Expr *EndExpr =
nullptr;
17371 if (Seg < FillIdx) {
17372 StartExpr = MakeIntLit(LeftAccum);
17373 LeftAccum += CountValues[Seg];
17374 EndExpr = MakeIntLit(LeftAccum);
17375 }
else if (Seg == FillIdx) {
17376 StartExpr = MakeIntLit(LeftAccum);
17377 if (RightRemaining == 0) {
17378 EndExpr = NumIterExpr;
17381 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
17382 MakeIntLit(RightRemaining));
17383 if (!Sub.isUsable())
17385 EndExpr = Sub.get();
17388 if (RightRemaining == RightSum) {
17390 StartExpr = NumIterExpr;
17393 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
17394 MakeIntLit(RightRemaining));
17395 if (!Sub.isUsable())
17397 StartExpr = Sub.get();
17401 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
17402 MakeIntLit(RightRemaining));
17403 if (!Sub.isUsable())
17405 StartExpr = Sub.get();
17407 RightRemaining -= CountValues[Seg];
17408 if (RightRemaining == 0)
17409 EndExpr = NumIterExpr;
17412 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
17413 MakeIntLit(RightRemaining));
17414 if (!Sub.isUsable())
17416 EndExpr = Sub.get();
17421 IVName += (Twine(Seg) +
"." + OrigVarName).str();
17423 auto MakeIVRef = [&
SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
17427 SemaRef.AddInitializerToDecl(IVDecl, StartExpr,
false);
17434 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeIVRef(), EndExpr);
17439 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeIVRef());
17444 IterationVarRef, MakeIVRef());
17449 BodyStmts.push_back(IVAssign.
get());
17450 BodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
17451 if (
auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
17453 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
17455 VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
17460 CurScope, OrigVarLoc, BO_Assign, LVRef, LoopVar->
getInit());
17463 BodyStmts.push_back(LVAssign.
get());
17466 BodyStmts.push_back(Body);
17472 auto *For =
new (Context)
17475 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17476 SplitLoops.push_back(For);
17481 SplitLoops.front()->getBeginLoc(), SplitLoops.back()->getEndLoc());
17484 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, SplitStmt,
17502 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
17503 size_t NumLoops = PermutationClause ? PermutationClause->
getNumLoops() : 2;
17507 Stmt *Body =
nullptr;
17510 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
17511 LoopHelpers, Body, OriginalInits,
17518 NumLoops, AStmt,
nullptr,
nullptr,
17523 if (PermutationClause &&
17524 llvm::is_contained(PermutationClause->
getArgsRefs(),
nullptr))
17527 assert(LoopHelpers.size() == NumLoops &&
17528 "Expecting loop iteration space dimensionaly to match number of "
17530 assert(OriginalInits.size() == NumLoops &&
17531 "Expecting loop iteration space dimensionaly to match number of "
17536 if (!PermutationClause) {
17537 Permutation = {1, 0};
17540 llvm::BitVector Flags(PermArgs.size());
17541 for (
Expr *PermArg : PermArgs) {
17542 std::optional<llvm::APSInt> PermCstExpr =
17543 PermArg->getIntegerConstantExpr(Context);
17546 uint64_t PermInt = PermCstExpr->getLimitedValue();
17547 assert(1 <= PermInt && PermInt <= NumLoops &&
17548 "Must be a permutation; diagnostic emitted in "
17549 "ActOnOpenMPPermutationClause");
17550 if (Flags[PermInt - 1]) {
17551 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
17552 Diag(PermArg->getExprLoc(),
17553 diag::err_omp_interchange_permutation_value_repeated)
17554 << PermInt << ExprRange;
17557 Flags[PermInt - 1] =
true;
17559 Permutation.push_back(PermInt - 1);
17562 if (Permutation.size() != NumLoops)
17567 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](
auto P) {
17568 auto [Idx, Arg] = P;
17572 NumLoops, AStmt, AStmt,
nullptr,
17581 for (
auto I : llvm::seq<int>(NumLoops)) {
17582 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
17584 assert(LoopHelper.Counters.size() == 1 &&
17585 "Single-dimensional loop iteration space expected");
17593 CaptureVars CopyTransformer(
SemaRef);
17596 auto MakeNotEmpty = [&]() ->
Expr * {
17597 Expr *NotEmpty =
nullptr;
17598 for (
const OMPLoopBasedDirective::HelperExprs &Helper : LoopHelpers) {
17600 AssertSuccess(CopyTransformer.TransformExpr(Helper.NumIterations));
17602 CurScope, NumIters->
getExprLoc(), BO_NE, NumIters,
17606 NotEmpty, HasIters))
17615 Stmt *Inner = Body;
17616 for (
auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
17618 uint64_t SourceIdx = Permutation[TargetIdx];
17619 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
17620 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
17621 assert(SourceHelper.Counters.size() == 1 &&
17622 "Single-dimensional loop iteration space expected");
17629 "Expected the logical iteration counter to be an integer");
17631 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
17636 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() ->
Expr * {
17638 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
17645 PermutedCntName.append({llvm::utostr(TargetIdx),
".iv.", OrigVarName});
17647 PermutedCntDecl->setDeclName(
17648 &
SemaRef.PP.getIdentifierTable().get(PermutedCntName));
17649 PermutedIndVars[TargetIdx] = PermutedCntDecl;
17650 auto MakePermutedRef = [
this, PermutedCntDecl, IVTy, OrigVarLoc]() {
17659 if (!
Zero.isUsable())
17661 SemaRef.AddInitializerToDecl(PermutedCntDecl,
Zero.get(),
17665 OrigCntVar->getEndLoc());
17673 Expr *UpperBound = MakeNumIterations();
17676 if (TargetIdx == 0) {
17679 SemaRef.ActOnConditionalOp(OrigVarLoc, OrigVarLoc, MakeNotEmpty(),
17680 UpperBound, NoIterations.
get());
17683 UpperBound = Guarded.
get();
17686 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
17687 MakePermutedRef(), UpperBound);
17696 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
17701 SourceHelper.Updates.end());
17702 if (
auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
17703 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
17704 BodyParts.push_back(Inner);
17707 Inner =
new (Context)
ForStmt(
17708 Context, InitStmt.
get(), CondExpr.
get(),
nullptr, IncrStmt.
get(), Inner,
17709 SourceHelper.Init->
getBeginLoc(), SourceHelper.Init->getBeginLoc(),
17710 SourceHelper.Inc->getEndLoc());
17714 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, Inner,
17732 unsigned NumLoops = 2;
17733 bool DepthIsDependent =
false;
17734 const auto *DepthClause =
17735 OMPExecutableDirective::getSingleClause<OMPDepthClause>(Clauses);
17737 Expr *DepthExpr = DepthClause->getDepth();
17739 DepthIsDependent =
true;
17740 }
else if (DepthExpr) {
17743 NumLoops = EvalResult.
Val.
getInt().getLimitedValue(
17744 std::numeric_limits<unsigned>::max());
17752 if (!DepthIsDependent) {
17753 unsigned WalkLimit = DepthClause ? NumLoops : 3;
17754 unsigned Found = 0;
17755 bool Enough = OMPLoopBasedDirective::doForAllLoops(
17757 WalkLimit, [&](
unsigned Cnt,
Stmt *S) {
17758 if (!isa<ForStmt>(S) && !isa<CXXForRangeStmt>(S))
17763 if (DepthClause && !Enough) {
17766 << getOpenMPDirectiveName(OMPD_flatten) << NumLoops << (
Found > 0)
17770 if (!DepthClause &&
Found >= 3) {
17771 Diag(StartLoc, diag::warn_omp_flatten_omitted_depth);
17772 if (
SemaRef.getLangOpts().OpenMP >= 61)
17773 Diag(StartLoc, diag::note_omp_flatten_insert_depth)
17780 if (DepthIsDependent)
17782 NumLoops, AStmt,
nullptr,
nullptr,
17787 Stmt *Body =
nullptr;
17790 if (!checkTransformableLoopNest(OMPD_flatten, AStmt, NumLoops, LoopHelpers,
17791 Body, OriginalInits, &NestedFinals))
17797 NumLoops, AStmt,
nullptr,
nullptr,
17800 assert(LoopHelpers.size() == NumLoops &&
17801 "Expecting loop iteration space dimensionality to match number of "
17803 assert(OriginalInits.size() == NumLoops &&
17804 "Expecting loop iteration space dimensionality to match number of "
17813 for (
auto I : llvm::seq<unsigned>(NumLoops)) {
17814 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
17815 assert(LoopHelper.Counters.size() == 1 &&
17816 "Single-dimensional loop iteration space expected");
17822 CaptureVars CopyTransformer(
SemaRef);
17825 auto MakeNumIterations = [&CopyTransformer, &LoopHelpers, &Context,
17828 ExprResult N = CopyTransformer.TransformExpr(LoopHelpers[I].NumIterations);
17838 VarIsInt && Context.getTypeSize(
Type) > Context.getTypeSize(VarType);
17840 UseVarWidth ? Context.getTypeSize(VarType) : Context.getTypeSize(
Type);
17844 N =
SemaRef.PerformImplicitConversion(
17851 OMPLoopBasedDirective::HelperExprs &OutermostHelper = LoopHelpers[0];
17854 SourceLocation OrigVarLocBegin = OutermostCntVar->getBeginLoc();
17860 auto BuildTripCount = [&](
unsigned Bits) ->
ExprResult {
17862 for (
unsigned I = 0; I < NumLoops; ++I) {
17872 Product =
SemaRef.BuildBinOp(CurScope, CondLoc, BO_Mul, Product.
get(),
17880 bool AllCountsLessThan32Bits =
17881 llvm::all_of(llvm::seq<unsigned>(NumLoops), [&](
unsigned I) {
17882 return Context.getTypeSize(LoopHelpers[I].NumIterations->getType()) <
17887 if (AllCountsLessThan32Bits || NumLoops == 1) {
17888 TripCount = BuildTripCount(32);
17890 ExprResult TripCount64 = BuildTripCount(64);
17893 TripCount = TripCount64;
17895 ExprResult TripCount32 = BuildTripCount(32);
17897 Context.getTypeSize(TripCount32.
get()->
getType()) == 32 &&
17902 TripCount = TripCount32;
17905 if (!TripCount.isUsable())
17908 QualType IVTy = TripCount.get()->getType();
17909 uint64_t IVWidth = Context.getTypeSize(IVTy);
17913 auto BuildHasIterations = [&](
unsigned Count) ->
ExprResult {
17915 for (
unsigned I = 0; I < Count; ++I) {
17917 CopyTransformer.TransformExpr(LoopHelpers[I].PreCond);
17924 LoopPreCond.
get());
17934 ExprResult HasIterations = BuildHasIterations(NumLoops);
17938 Context, llvm::APInt::getZero(IVWidth), IVTy, CondLoc);
17939 TripCount =
SemaRef.ActOnConditionalOp(CondLoc, CondLoc, HasIterations.
get(),
17940 TripCount.get(), ZeroTripCount);
17941 if (!TripCount.isUsable())
17944 auto MakeNumIterationsInIVTy = [&](
unsigned I) ->
ExprResult {
17948 return SemaRef.PerformImplicitConversion(
17954 auto MakeDivisorInIVTy = [&](
unsigned I) ->
ExprResult {
17956 ExprResult NCmp = MakeNumIterationsInIVTy(I);
17959 auto MakeCst = [&](uint64_t
V) ->
Expr * {
17964 SemaRef.BuildBinOp(CurScope, CondLoc, BO_EQ, NCmp.
get(), MakeCst(0));
17967 return SemaRef.ActOnConditionalOp(CondLoc, CondLoc, IsZero.
get(),
17968 MakeCst(1), N.
get());
17983 nullptr, OutermostCntVar);
17984 auto MakeFlattenedRef = [&
SemaRef = this->SemaRef, FlattenedIVDecl, IVTy,
17995 SemaRef.AddInitializerToDecl(FlattenedIVDecl,
Zero,
false);
17998 if (!
Init.isUsable())
18006 MakeFlattenedRef(), TripCount.get());
18015 SemaRef.BuildUnaryOp(CurScope, OutermostHelper.Inc->getExprLoc(),
18016 UO_PreInc, MakeFlattenedRef());
18023 for (
unsigned I = 0; I < NumLoops; ++I) {
18024 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
18027 std::string IVName = (
".flatten.iv." + llvm::Twine(I)).str();
18028 IVDecl->setDeclName(&
SemaRef.PP.getIdentifierTable().get(IVName));
18031 if (I + 1 < NumLoops) {
18032 ExprResult Divisor = MakeDivisorInIVTy(I + 1);
18035 for (
unsigned J = I + 2; J < NumLoops; ++J) {
18037 if (!
Next.isUsable())
18039 Divisor =
SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Mul,
18046 if (!
Value.isUsable())
18050 ExprResult RemDivisor = MakeDivisorInIVTy(I);
18055 if (!
Value.isUsable())
18059 SemaRef.AddInitializerToDecl(IVDecl,
Value.get(),
false);
18065 BodyStmts.push_back(IVStmt.
get());
18066 llvm::append_range(BodyStmts, LoopHelper.Updates);
18067 if (
auto *CXXFor = dyn_cast<CXXForRangeStmt>(LoopStmts[I]))
18068 BodyStmts.push_back(CXXFor->getLoopVarStmt());
18070 BodyStmts.push_back(Body);
18071 auto *FlattenedBody =
18075 auto *FlattenedFor =
new (Context)
ForStmt(
18076 Context,
Init.get(), Cond.
get(),
nullptr, Incr.
get(), FlattenedBody,
18077 OutermostHelper.Init->
getBeginLoc(), OutermostHelper.Init->getBeginLoc(),
18078 OutermostHelper.Inc->getEndLoc());
18085 for (
unsigned I = 0; I < NumLoops; ++I) {
18086 assert(LoopHelpers[I].Finals.size() == 1 &&
18087 "Single-dimensional loop iteration space expected");
18089 CopyTransformer.TransformExpr(LoopHelpers[I].Finals.front());
18090 if (!Final.isUsable())
18092 ExprResult FinalCond = BuildHasIterations(I + 1);
18096 Stmt *Then = Final.get();
18097 if (
Stmt *Nested = NestedFinals[I])
18101 nullptr,
nullptr, FinalCond.
get(), CondLoc,
18105 FlattenedFor->getBeginLoc(),
18106 FlattenedFor->getEndLoc());
18109 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, FlattenedFor,
18121 CaptureVars CopyTransformer(
SemaRef);
18127 if (
const auto *DepthC =
18128 OMPExecutableDirective::getSingleClause<OMPDepthClause>(Clauses)) {
18129 Diag(DepthC->getBeginLoc(), diag::err_omp_clause_not_supported_yet)
18130 <<
"depth" << getOpenMPDirectiveName(OMPD_fuse);
18140 1, AStmt,
nullptr,
nullptr,
18145 LoopSequenceAnalysis SeqAnalysis;
18146 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
18151 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
18152 "Inconsistent size of the loop sequence and the number of loops "
18153 "found in the sequence");
18157 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
18161 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
18166 auto EvaluateLoopRangeArguments = [&Context](
Expr *
First,
Expr *Count,
18167 uint64_t &FirstVal,
18168 uint64_t &CountVal) {
18169 llvm::APSInt FirstInt =
First->EvaluateKnownConstInt(Context);
18170 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
18171 FirstVal = FirstInt.getLimitedValue();
18172 CountVal = CountInt.getLimitedValue();
18178 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
18179 unsigned NumLoops) ->
bool {
18180 return FirstVal + CountVal - 1 <= NumLoops;
18182 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
18188 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
18191 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
18192 << getOpenMPDirectiveName(OMPD_fuse);
18194 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
18195 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
18196 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
18197 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
18201 LastVal = FirstVal + CountVal - 1;
18206 unsigned NumGeneratedTopLevelLoops =
18207 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
18211 if (SeqAnalysis.LoopSeqSize == 1)
18213 << getOpenMPDirectiveName(OMPD_fuse);
18217 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
18218 for (
unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
18220 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
18221 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
18222 IVType = CurrentIVType;
18225 uint64_t IVBitWidth = Context.getIntWidth(IVType);
18237 auto CreateHelperVarAndStmt =
18239 unsigned I,
bool NeedsNewVD =
false) {
18240 Expr *TransformedExpr =
18242 if (!TransformedExpr)
18243 return std::pair<VarDecl *, StmtResult>(
nullptr,
StmtError());
18245 auto Name = (Twine(
".omp.") + BaseName + std::to_string(I)).str();
18250 SemaRef.AddInitializerToDecl(VD, TransformedExpr,
false);
18260 return std::make_pair(VD,
DeclStmt);
18278 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
18289 for (
unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
18290 if (SeqAnalysis.Loops[I].isRegularLoop()) {
18292 SeqAnalysis.Loops[I].TheForStmt,
18293 SeqAnalysis.Loops[I].OriginalInits, PreInits);
18294 }
else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
18298 llvm::append_range(PreInits, SeqAnalysis.Loops[I].TransformsPreInits);
18301 SeqAnalysis.Loops[I].TheForStmt,
18302 SeqAnalysis.Loops[I].OriginalInits, PreInits);
18304 auto [LBVD, LBDStmt] =
18305 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB,
"lb", J);
18306 auto [STVD, STDStmt] =
18307 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST,
"st", J);
18308 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
18309 SeqAnalysis.Loops[I].HelperExprs.NumIterations,
"ni", J,
true);
18310 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
18311 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef,
"iv", J);
18313 assert(LBVD && STVD && NIVD && IVVD &&
18314 "OpenMP Fuse Helper variables creation failed");
18316 LBVarDecls.push_back(LBVD);
18317 STVarDecls.push_back(STVD);
18318 NIVarDecls.push_back(NIVD);
18319 IVVarDecls.push_back(IVVD);
18321 PreInits.push_back(LBDStmt.get());
18322 PreInits.push_back(STDStmt.get());
18323 PreInits.push_back(NIDStmt.get());
18324 PreInits.push_back(IVDStmt.get());
18357 StringRef IndexName =
".omp.fuse.index";
18362 SemaRef.AddInitializerToDecl(IndexDecl, InitVal,
false);
18369 auto MakeIVRef = [&
SemaRef = this->SemaRef, IndexDecl, IVType,
18387 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
18388 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
18396 std::string TempName = (Twine(
".omp.temp.") + Twine(J)).str();
18410 PreInits.push_back(TempStmt.
get());
18419 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
18433 const std::string MaxName = Twine(
".omp.fuse.max").str();
18441 if (MaxStmt.isInvalid())
18443 PreInits.push_back(MaxStmt.get());
18447 MakeIVRef(), MaxRef);
18473 for (
unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
18478 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
18482 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.
get());
18487 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.
get());
18493 BodyStmts.push_back(IdxExpr.
get());
18494 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
18497 if (
auto *SourceCXXFor =
18498 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
18499 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
18503 ?
cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
18505 BodyStmts.push_back(Body);
18512 MakeVarDeclRef(NIVarDecls[J]));
18522 FusedBodyStmts.push_back(IfStatement);
18528 ForStmt *FusedForStmt =
new (Context)
18536 for (
unsigned I : llvm::seq<unsigned>(FirstVal - 1, LastVal)) {
18537 const LoopAnalysis &
Loop = SeqAnalysis.Loops[I];
18538 if (
Loop.isRegularLoop())
18541 AllFinalsStmts.push_back(Own);
18542 if (
Loop.TransformFinals)
18543 AllFinalsStmts.push_back(
Loop.TransformFinals);
18545 Stmt *CombinedFinals =
nullptr;
18546 if (AllFinalsStmts.size() == 1)
18547 CombinedFinals = AllFinalsStmts.front();
18548 else if (!AllFinalsStmts.empty())
18568 Stmt *FusionStmt = FusedForStmt;
18569 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
18576 for (
unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
18577 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1)
18581 if (SeqAnalysis.Loops[I].isLoopTransformation())
18582 llvm::append_range(PreInits, SeqAnalysis.Loops[I].TransformsPreInits);
18587 FinalLoops.push_back(WithFinals(SeqAnalysis.Loops[I].TheForStmt,
18588 SeqAnalysis.Loops[I].TransformFinals));
18593 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1),
18594 WithFinals(FusedForStmt, CombinedFinals));
18595 CombinedFinals =
nullptr;
18600 Context, StartLoc, EndLoc, Clauses, NumGeneratedTopLevelLoops, AStmt,
18601 FusionStmt,
buildPreInits(Context, PreInits), CombinedFinals);
18620 case OMPC_allocator:
18623 case OMPC_collapse:
18632 case OMPC_priority:
18644 case OMPC_novariants:
18647 case OMPC_nocontext:
18665 case OMPC_ompx_dyn_cgroup_mem:
18671 case OMPC_transparent:
18674 case OMPC_dyn_groupprivate:
18675 case OMPC_grainsize:
18676 case OMPC_num_tasks:
18677 case OMPC_num_threads:
18681 case OMPC_proc_bind:
18682 case OMPC_schedule:
18684 case OMPC_firstprivate:
18685 case OMPC_lastprivate:
18687 case OMPC_reduction:
18688 case OMPC_task_reduction:
18689 case OMPC_in_reduction:
18693 case OMPC_copyprivate:
18695 case OMPC_mergeable:
18696 case OMPC_threadprivate:
18697 case OMPC_groupprivate:
18699 case OMPC_allocate:
18716 case OMPC_dist_schedule:
18717 case OMPC_defaultmap:
18722 case OMPC_use_device_ptr:
18723 case OMPC_use_device_addr:
18724 case OMPC_is_device_ptr:
18725 case OMPC_unified_address:
18726 case OMPC_unified_shared_memory:
18727 case OMPC_reverse_offload:
18728 case OMPC_dynamic_allocators:
18729 case OMPC_atomic_default_mem_order:
18730 case OMPC_self_maps:
18731 case OMPC_device_type:
18733 case OMPC_nontemporal:
18736 case OMPC_severity:
18738 case OMPC_inclusive:
18739 case OMPC_exclusive:
18740 case OMPC_uses_allocators:
18741 case OMPC_affinity:
18744 case OMPC_num_teams:
18745 case OMPC_thread_limit:
18747 llvm_unreachable(
"Clause is not allowed.");
18759 llvm::omp::Version OMPVersion,
18761 assert(isAllowedClauseForDirective(DKind, CKind, OMPVersion) &&
18762 "Invalid directive with CKind-clause");
18765 if (NameModifier != OMPD_unknown &&
18766 !isAllowedClauseForDirective(NameModifier, CKind, OMPVersion))
18767 return OMPD_unknown;
18786 case OMPD_teams_loop:
18787 case OMPD_target_teams_loop:
18791 case OMPD_target_update:
18792 case OMPD_target_enter_data:
18793 case OMPD_target_exit_data:
18799 case OMPC_num_teams:
18800 case OMPC_thread_limit:
18801 case OMPC_ompx_dyn_cgroup_mem:
18802 case OMPC_dyn_groupprivate:
18804 if (Leafs[0] == OMPD_target)
18805 return OMPD_target;
18808 if (Leafs[0] == OMPD_target ||
18809 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
18810 OMPD_target_enter_data, OMPD_target_exit_data},
18814 case OMPC_novariants:
18815 case OMPC_nocontext:
18816 if (DKind == OMPD_dispatch)
18820 if (DKind == OMPD_metadirective)
18821 return OMPD_metadirective;
18824 return OMPD_unknown;
18837 int InnermostIdx = [&]() {
18838 for (
int I = EndIdx - 1; I >= 0; --I) {
18839 if (isAllowedClauseForDirective(Leafs[I], Clause, OMPVersion))
18847 for (
int I = InnermostIdx - 1; I >= 0; --I) {
18852 if (Regions[0] != OMPD_unknown)
18853 return Regions.back();
18855 return OMPD_unknown;
18860 for (
int I = 0, E = Leafs.size(); I != E; ++I) {
18861 if (Leafs[I] == Dir)
18867 int End = NameModifier == OMPD_unknown ? Leafs.size()
18868 : GetLeafIndex(NameModifier);
18869 return GetEnclosingRegion(End, CKind);
18872 return OMPD_unknown;
18880 Stmt *HelperValStmt =
nullptr;
18883 !
Condition->isInstantiationDependent() &&
18884 !
Condition->containsUnexpandedParameterPack()) {
18889 ValExpr = Val.
get();
18893 DKind, OMPC_if,
getLangOpts().getOpenMPVersion(), NameModifier);
18894 if (CaptureRegion != OMPD_unknown &&
18895 !
SemaRef.CurContext->isDependentContext()) {
18896 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18897 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18898 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18904 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
18905 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
18913 Stmt *HelperValStmt =
nullptr;
18916 !
Condition->isInstantiationDependent() &&
18917 !
Condition->containsUnexpandedParameterPack()) {
18922 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
18926 DKind, OMPC_final,
getLangOpts().getOpenMPVersion());
18927 if (CaptureRegion != OMPD_unknown &&
18928 !
SemaRef.CurContext->isDependentContext()) {
18929 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
18930 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18931 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
18937 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18948 IntConvertDiagnoser()
18949 : ICEConvertDiagnoser(
false,
false,
true) {}
18952 return S.
Diag(Loc, diag::err_omp_not_integral) <<
T;
18956 return S.
Diag(Loc, diag::err_omp_incomplete_type) <<
T;
18961 return S.
Diag(Loc, diag::err_omp_explicit_conversion) <<
T << ConvTy;
18970 return S.
Diag(Loc, diag::err_omp_ambiguous_conversion) <<
T;
18979 llvm_unreachable(
"conversion functions are permitted");
18981 } ConvertDiagnoser;
18982 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
18987 bool StrictlyPositive,
bool BuildCapture =
false,
18990 Stmt **HelperValStmt =
nullptr) {
18996 if (
Value.isInvalid())
18999 ValExpr =
Value.get();
19001 if (std::optional<llvm::APSInt>
Result =
19003 if (
Result->isSigned() &&
19004 !((!StrictlyPositive &&
Result->isNonNegative()) ||
19005 (StrictlyPositive &&
Result->isStrictlyPositive()))) {
19006 SemaRef.
Diag(Loc, diag::err_omp_negative_expression_in_clause)
19016 if (*CaptureRegion != OMPD_unknown &&
19019 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19020 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
19031 llvm::raw_svector_ostream
Out(Buffer);
19032 unsigned Skipped = Exclude.size();
19033 for (
unsigned I =
First; I <
Last; ++I) {
19034 if (llvm::is_contained(Exclude, I)) {
19039 if (I + Skipped + 2 ==
Last)
19041 else if (I + Skipped + 1 !=
Last)
19044 return std::string(
Out.str());
19054 if (ComplexModifierLoc.
isValid() &&
19055 (ComplexModifier != OMPC_NUMTHREADS_dims || !ComplexModifierExpr)) {
19056 Diag(ComplexModifierLoc, diag::err_omp_malformed_complex_modifier)
19058 << getOpenMPClauseName(OMPC_num_threads);
19061 if (SimpleModifierLoc.
isValid() && SimpleModifier == OMPC_NUMTHREADS_dims) {
19062 Diag(SimpleModifierLoc, diag::err_omp_malformed_complex_modifier)
19064 << getOpenMPClauseName(OMPC_num_threads);
19067 if (SimpleModifierLoc.
isValid() && SimpleModifier != OMPC_NUMTHREADS_strict) {
19068 Diag(SimpleModifierLoc, diag::err_omp_unexpected_clause_value)
19070 OMPC_NUMTHREADS_strict)
19071 << getOpenMPClauseName(OMPC_num_threads);
19075 if (VarList.empty())
19079 for (
Expr *&ValExpr : Vars) {
19087 if (ComplexModifier == OMPC_NUMTHREADS_dims) {
19089 ComplexModifierExpr,
19090 ComplexModifierLoc, Vars, EndLoc);
19093 ComplexModifierExpr = Res.
get();
19096 ComplexModifierExpr))
19099 if (SimpleModifier == OMPC_NUMTHREADS_strict &&
getLangOpts().OpenMP < 60) {
19100 Diag(SimpleModifierLoc, diag::err_omp_modifier_requires_version)
19102 << getOpenMPClauseName(OMPC_num_threads) <<
"6.0";
19108 DKind, OMPC_num_threads,
getLangOpts().getOpenMPVersion());
19109 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
19111 getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, Vars,
19112 SimpleModifier, ComplexModifier, SimpleModifierLoc, ComplexModifierLoc,
19113 ComplexModifierExpr,
nullptr);
19115 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19116 for (
Expr *&ValExpr : Vars) {
19117 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
19118 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
19120 if (ComplexModifierExpr) {
19121 ComplexModifierExpr =
SemaRef.MakeFullExpr(ComplexModifierExpr).get();
19122 ComplexModifierExpr =
19123 tryBuildCapture(
SemaRef, ComplexModifierExpr, Captures).get();
19128 getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, Vars,
19129 SimpleModifier, ComplexModifier, SimpleModifierLoc, ComplexModifierLoc,
19130 ComplexModifierExpr, PreInit);
19135 bool SuppressExprDiags) {
19144 if (SuppressExprDiags) {
19148 SuppressedDiagnoser() : VerifyICEDiagnoser(
true) {}
19151 llvm_unreachable(
"Diagnostic suppressed");
19154 ICE =
SemaRef.VerifyIntegerConstantExpression(E, &
Result, Diagnoser,
19164 if ((StrictlyPositive && !
Result.isStrictlyPositive()) ||
19165 (!StrictlyPositive && !
Result.isNonNegative())) {
19166 Diag(E->
getExprLoc(), diag::err_omp_negative_expression_in_clause)
19171 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
19172 CKind == OMPC_allocate) &&
19174 Diag(E->
getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
19179 if (!
Result.isRepresentableByInt64()) {
19185 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
19187 else if (CKind == OMPC_ordered)
19206 if (
Result.isNonNegative()) {
19210 diag::err_omp_negative_expression_in_clause)
19213 }
else if (
auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
19220 Diag(DeviceNumExpr->
getExprLoc(), diag::err_expected_expression);
19254 DSAStackTy *Stack) {
19255 if (!Stack->getOMPAllocatorHandleT().isNull())
19262 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
19263 <<
"omp_allocator_handle_t";
19270 bool ErrorFound =
false;
19271 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
19272 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
19273 StringRef Allocator =
19274 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
19276 auto *VD = dyn_cast_or_null<ValueDecl>(
19296 Stack->setAllocator(AllocatorKind, Res.
get());
19299 S.
Diag(Loc, diag::err_omp_implied_type_not_found)
19300 <<
"omp_allocator_handle_t";
19307 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
19324 Allocator =
SemaRef.PerformImplicitConversion(
19325 Allocator.
get(),
DSAStack->getOMPAllocatorHandleT(),
19354 Expr *NumForLoops) {
19360 if (NumForLoops && LParenLoc.
isValid()) {
19365 NumForLoops = NumForLoopsResult.
get();
19367 NumForLoops =
nullptr;
19371 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
19372 StartLoc, LParenLoc, EndLoc);
19373 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
19382 case OMPC_proc_bind:
19384 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19386 case OMPC_atomic_default_mem_order:
19389 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19393 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19395 case OMPC_update_depend_objects:
19398 LParenLoc, EndLoc);
19402 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19406 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19408 case OMPC_severity:
19411 LParenLoc, EndLoc);
19413 case OMPC_threadset:
19415 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19419 case OMPC_num_threads:
19424 case OMPC_allocator:
19425 case OMPC_collapse:
19426 case OMPC_schedule:
19428 case OMPC_firstprivate:
19429 case OMPC_lastprivate:
19431 case OMPC_reduction:
19432 case OMPC_task_reduction:
19433 case OMPC_in_reduction:
19437 case OMPC_copyprivate:
19441 case OMPC_mergeable:
19442 case OMPC_threadprivate:
19443 case OMPC_groupprivate:
19444 case OMPC_allocate:
19462 case OMPC_num_teams:
19463 case OMPC_thread_limit:
19464 case OMPC_priority:
19465 case OMPC_grainsize:
19467 case OMPC_num_tasks:
19469 case OMPC_dist_schedule:
19471 case OMPC_defaultmap:
19476 case OMPC_use_device_ptr:
19477 case OMPC_use_device_addr:
19478 case OMPC_is_device_ptr:
19479 case OMPC_has_device_addr:
19480 case OMPC_unified_address:
19481 case OMPC_unified_shared_memory:
19482 case OMPC_reverse_offload:
19483 case OMPC_dynamic_allocators:
19484 case OMPC_self_maps:
19485 case OMPC_device_type:
19487 case OMPC_nontemporal:
19489 case OMPC_novariants:
19490 case OMPC_nocontext:
19492 case OMPC_inclusive:
19493 case OMPC_exclusive:
19494 case OMPC_uses_allocators:
19495 case OMPC_affinity:
19499 llvm_unreachable(
"Clause is not allowed.");
19508 if (M == OMP_DEFAULT_unknown) {
19509 Diag(MLoc, diag::err_omp_unexpected_clause_value)
19511 unsigned(OMP_DEFAULT_unknown))
19516 Diag(VCKindLoc, diag::err_omp_default_vc)
19521 bool IsTargetDefault =
19528 if (IsTargetDefault && M == OMP_DEFAULT_shared)
19531 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
19537 case OMP_DEFAULT_none:
19538 if (IsTargetDefault)
19539 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
19541 DSAStack->setDefaultDSANone(MLoc);
19543 case OMP_DEFAULT_firstprivate:
19544 if (IsTargetDefault)
19545 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
19547 DSAStack->setDefaultDSAFirstPrivate(MLoc);
19549 case OMP_DEFAULT_private:
19550 if (IsTargetDefault)
19551 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
19553 DSAStack->setDefaultDSAPrivate(MLoc);
19555 case OMP_DEFAULT_shared:
19556 assert(!IsTargetDefault &&
"DSA shared invalid with target directive");
19557 DSAStack->setDefaultDSAShared(MLoc);
19560 llvm_unreachable(
"unexpected DSA in OpenMP default clause");
19564 case OMPC_DEFAULT_VC_aggregate:
19565 if (IsTargetDefault)
19566 DefMapKind = OMPC_DEFAULTMAP_aggregate;
19568 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
19570 case OMPC_DEFAULT_VC_pointer:
19571 if (IsTargetDefault)
19572 DefMapKind = OMPC_DEFAULTMAP_pointer;
19574 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
19576 case OMPC_DEFAULT_VC_scalar:
19577 if (IsTargetDefault)
19578 DefMapKind = OMPC_DEFAULTMAP_scalar;
19580 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
19582 case OMPC_DEFAULT_VC_all:
19583 if (IsTargetDefault)
19584 DefMapKind = OMPC_DEFAULTMAP_all;
19586 DSAStack->setDefaultDSAVCAll(VCKindLoc);
19589 llvm_unreachable(
"unexpected variable category in OpenMP default clause");
19598 if (IsTargetDefault) {
19599 if (DefMapKind == OMPC_DEFAULTMAP_all) {
19600 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
19601 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
19602 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
19604 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
19609 SetDefaultClauseAttrs(M, VCKind);
19611 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
19620 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
19623 << getOpenMPClauseName(OMPC_threadset);
19640 return new (Ctx) OMPTransparentClause(ER.
get(), HelperValStmt, CaptureRegion,
19641 StartLoc, LParenLoc, EndLoc);
19648 Stmt *HelperValStmt =
nullptr;
19651 DKind, OMPC_transparent,
getLangOpts().getOpenMPVersion());
19652 if (CaptureRegion != OMPD_unknown &&
19653 !
SemaRef.CurContext->isDependentContext()) {
19654 Expr *ValExpr =
SemaRef.MakeFullExpr(ImpexTypeArg).get();
19655 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19656 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
19659 if (!ImpexTypeArg) {
19661 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19662 StartLoc, LParenLoc, EndLoc);
19673 SemaRef.Diag(StartLoc, diag::err_omp_implied_type_not_found)
19678 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19679 StartLoc, LParenLoc, EndLoc);
19684 HelperValStmt, CaptureRegion, StartLoc,
19685 LParenLoc, EndLoc);
19690 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(StartLoc,
19692 if (std::optional<llvm::APSInt>
Result =
19693 Value.get()->getIntegerConstantExpr(
SemaRef.Context)) {
19694 if (
Result->isNegative() ||
19697 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_value);
19700 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19701 StartLoc, LParenLoc, EndLoc);
19708 ImpexTypeArg, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19716 if (Kind == OMP_PROC_BIND_unknown) {
19717 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19719 unsigned(OMP_PROC_BIND_master),
19722 ? OMP_PROC_BIND_primary
19723 : OMP_PROC_BIND_spread) +
19728 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
19729 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19731 unsigned(OMP_PROC_BIND_master),
19733 unsigned(OMP_PROC_BIND_spread) + 1)
19736 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19743 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19745 OMPC_atomic_default_mem_order, 0,
19750 return new (
getASTContext()) OMPAtomicDefaultMemOrderClause(
19751 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19760 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19767 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19776 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19783 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19790 assert(ME &&
"NULL expr in Message clause");
19799 Stmt *HelperValStmt =
nullptr;
19805 DKind == OMPD_unknown
19809 if (CaptureRegion != OMPD_unknown &&
19810 !
SemaRef.CurContext->isDependentContext()) {
19811 ME =
SemaRef.MakeFullExpr(ME).get();
19812 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19813 ME = tryBuildCapture(
SemaRef, ME, Captures).get();
19818 ME =
SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
19821 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19828 if (Kind != OMPC_ORDER_concurrent ||
19833 "OMPC_ORDER_unknown not greater than 0");
19835 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
19844 Diag(MLoc, diag::err_omp_unexpected_clause_value)
19850 DSAStack->setRegionHasOrderConcurrent(
true);
19853 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
19854 DSAStack->getCurScope()->setFlags(existingFlags |
19859 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
19866 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
19868 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
19869 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
19871 Except.push_back(OMPC_DEPEND_inoutset);
19872 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19878 return OMPUpdateDependObjectsClause::Create(
19879 getASTContext(), StartLoc, LParenLoc, KindKwLoc, Kind, EndLoc);
19888 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
19898 QualType SizeTy = SizeExpr->getType();
19927 if (!SizeExpr->isInstantiationDependent() && !IsValid)
19928 SizeExpr =
nullptr;
19932 SanitizedSizeExprs);
19939 std::optional<unsigned> FillIdx,
19941 unsigned FillCount) {
19948 for (
unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
19949 Expr *&CountExpr = SanitizedCountExprs[I];
19950 if (FillIdx && I == *FillIdx)
19956 CountExpr, OMPC_counts,
false);
19958 CountExpr =
nullptr;
19960 CountExpr = Verified.
get();
19963 if (FillCount != 1) {
19964 Diag(FillCount == 0 ? StartLoc : FillLoc,
19965 diag::err_omp_split_counts_not_one_omp_fill);
19969 SanitizedCountExprs, FillIdx, FillLoc);
19976 size_t NumLoops = PermExprs.size();
19978 llvm::append_range(SanitizedPermExprs, PermExprs);
19980 for (
Expr *&PermExpr : SanitizedPermExprs) {
19983 if (!PermExpr || PermExpr->isInstantiationDependent())
19986 llvm::APSInt PermVal;
19989 bool IsValid = PermEvalExpr.
isUsable();
19991 PermExpr = PermEvalExpr.
get();
19993 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
19997 diag::err_omp_interchange_permutation_value_range)
19998 << NumLoops << ExprRange;
20002 if (!PermExpr->isInstantiationDependent() && !IsValid)
20003 PermExpr =
nullptr;
20007 EndLoc, SanitizedPermExprs);
20023 FactorExpr, OMPC_partial,
true);
20026 FactorExpr = FactorResult.
get();
20040 DepthExpr, OMPC_depth,
true);
20043 DepthExpr = DepthResult.
get();
20071 StartLoc, LParenLoc, FirstLoc, CountLoc, EndLoc,
First, Count);
20092 case OMPC_schedule: {
20093 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
20094 assert(Argument.size() == NumberOfElements &&
20095 ArgumentLoc.size() == NumberOfElements);
20100 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
20101 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
20105 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
20107 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
20110 case OMPC_dist_schedule:
20113 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
20116 enum { DefaultModifier, DefaultVarCategory };
20118 static_cast<llvm::omp::DefaultKind
>(Argument[DefaultModifier]),
20119 ArgumentLoc[DefaultModifier],
20121 Argument[DefaultVarCategory]),
20122 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
20124 case OMPC_defaultmap:
20125 enum { Modifier, DefaultmapKind };
20129 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
20133 enum { OrderModifier, OrderKind };
20137 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
20140 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
20143 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
20145 case OMPC_grainsize:
20146 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
20147 "Modifier for grainsize clause and its location are expected.");
20150 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
20152 case OMPC_num_tasks:
20153 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
20154 "Modifier for num_tasks clause and its location are expected.");
20157 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
20159 case OMPC_dyn_groupprivate: {
20160 enum { Modifier1, Modifier2, NumberOfElements };
20161 assert(Argument.size() == NumberOfElements &&
20162 ArgumentLoc.size() == NumberOfElements &&
20163 "Modifiers for dyn_groupprivate clause and their locations are "
20168 Argument[Modifier2]),
20169 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
20170 ArgumentLoc[Modifier2], EndLoc);
20178 case OMPC_allocator:
20179 case OMPC_collapse:
20180 case OMPC_proc_bind:
20182 case OMPC_firstprivate:
20183 case OMPC_lastprivate:
20185 case OMPC_reduction:
20186 case OMPC_task_reduction:
20187 case OMPC_in_reduction:
20191 case OMPC_copyprivate:
20195 case OMPC_mergeable:
20196 case OMPC_threadprivate:
20197 case OMPC_groupprivate:
20198 case OMPC_allocate:
20215 case OMPC_num_teams:
20216 case OMPC_thread_limit:
20217 case OMPC_priority:
20224 case OMPC_use_device_ptr:
20225 case OMPC_use_device_addr:
20226 case OMPC_is_device_ptr:
20227 case OMPC_has_device_addr:
20228 case OMPC_unified_address:
20229 case OMPC_unified_shared_memory:
20230 case OMPC_reverse_offload:
20231 case OMPC_dynamic_allocators:
20232 case OMPC_atomic_default_mem_order:
20233 case OMPC_self_maps:
20234 case OMPC_device_type:
20236 case OMPC_nontemporal:
20238 case OMPC_severity:
20241 case OMPC_novariants:
20242 case OMPC_nocontext:
20244 case OMPC_inclusive:
20245 case OMPC_exclusive:
20246 case OMPC_uses_allocators:
20247 case OMPC_affinity:
20251 llvm_unreachable(
"Clause is not allowed.");
20262 Excluded.push_back(M2);
20263 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
20264 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
20265 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
20266 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
20267 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
20290 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
20291 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
20292 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
20293 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
20294 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
20300 std::string Values;
20310 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
20319 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
20320 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
20321 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
20322 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
20323 diag::err_omp_schedule_nonmonotonic_static);
20326 Expr *ValExpr = ChunkSize;
20327 Stmt *HelperValStmt =
nullptr;
20338 ValExpr = Val.
get();
20343 if (std::optional<llvm::APSInt>
Result =
20345 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
20346 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
20351 DSAStack->getCurrentDirective(), OMPC_schedule,
20352 getLangOpts().getOpenMPVersion()) != OMPD_unknown &&
20353 !
SemaRef.CurContext->isDependentContext()) {
20354 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
20355 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20356 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20363 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
20364 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
20383 case OMPC_mergeable:
20431 case OMPC_unified_address:
20434 case OMPC_unified_shared_memory:
20437 case OMPC_reverse_offload:
20440 case OMPC_dynamic_allocators:
20443 case OMPC_self_maps:
20457 case OMPC_ompx_bare:
20462 case OMPC_num_threads:
20467 case OMPC_allocator:
20468 case OMPC_collapse:
20469 case OMPC_schedule:
20471 case OMPC_firstprivate:
20472 case OMPC_lastprivate:
20474 case OMPC_reduction:
20475 case OMPC_task_reduction:
20476 case OMPC_in_reduction:
20480 case OMPC_copyprivate:
20482 case OMPC_proc_bind:
20483 case OMPC_threadprivate:
20484 case OMPC_groupprivate:
20485 case OMPC_allocate:
20491 case OMPC_num_teams:
20492 case OMPC_thread_limit:
20493 case OMPC_priority:
20494 case OMPC_grainsize:
20495 case OMPC_num_tasks:
20497 case OMPC_dist_schedule:
20498 case OMPC_defaultmap:
20503 case OMPC_use_device_ptr:
20504 case OMPC_use_device_addr:
20505 case OMPC_is_device_ptr:
20506 case OMPC_has_device_addr:
20507 case OMPC_atomic_default_mem_order:
20508 case OMPC_device_type:
20510 case OMPC_nontemporal:
20513 case OMPC_severity:
20515 case OMPC_novariants:
20516 case OMPC_nocontext:
20518 case OMPC_inclusive:
20519 case OMPC_exclusive:
20520 case OMPC_uses_allocators:
20521 case OMPC_affinity:
20523 case OMPC_ompx_dyn_cgroup_mem:
20524 case OMPC_dyn_groupprivate:
20526 llvm_unreachable(
"Clause is not allowed.");
20538 !
Condition->isInstantiationDependent() &&
20539 !
Condition->containsUnexpandedParameterPack()) {
20544 ValExpr = Val.
get();
20549 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
20555 return new (
getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
20560 return new (
getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
20565 return new (
getASTContext()) OMPReadClause(StartLoc, EndLoc);
20570 return new (
getASTContext()) OMPWriteClause(StartLoc, EndLoc);
20575 return new (
getASTContext()) OMPUpdateClause(StartLoc, EndLoc);
20580 return new (
getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
20585 return new (
getASTContext()) OMPCompareClause(StartLoc, EndLoc);
20590 return new (
getASTContext()) OMPFailClause(StartLoc, EndLoc);
20600 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
20604 OMPFailClause(
Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
20609 return new (
getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
20614 return new (
getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
20619 return new (
getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
20624 return new (
getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
20629 return new (
getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
20634 return new (
getASTContext()) OMPWeakClause(StartLoc, EndLoc);
20654 return new (
getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
20660 return new (
getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
20665 return new (
getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
20671 return new (
getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
20676 return new (
getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
20686 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
20688 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
20689 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
20690 <<
Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
20703 bool HasInitClause =
false;
20704 bool IsTargetSync =
false;
20708 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
20709 HasInitClause =
true;
20710 if (InitClause->getIsTargetSync())
20711 IsTargetSync =
true;
20712 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
20716 if (DependClause && HasInitClause && !IsTargetSync) {
20717 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
20731 if (ClauseKind == OMPC_init) {
20734 }
else if (ClauseKind == OMPC_use) {
20737 }
else if (ClauseKind == OMPC_destroy) {
20743 if (!InteropVars.insert(
DeclResult.first).second) {
20744 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
20760 Expr *RefExpr = InteropVarExpr;
20775 bool HasError =
false;
20781 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
20782 InteropType =
QualType(TD->getTypeForDecl(), 0);
20791 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
20792 <<
"omp_interop_t";
20798 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
20804 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
20806 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
20824 StartLoc, LParenLoc, VarLoc, EndLoc);
20837 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
20846 DSAStack->getCurrentDirective() == OMPD_depobj) {
20848 Diag(StartLoc, diag::err_omp_expected_clause_argument)
20850 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
20866 Stmt *HelperValStmt =
nullptr;
20869 !
Condition->isInstantiationDependent() &&
20870 !
Condition->containsUnexpandedParameterPack()) {
20875 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
20879 DKind, OMPC_novariants,
getLangOpts().getOpenMPVersion());
20880 if (CaptureRegion != OMPD_unknown &&
20881 !
SemaRef.CurContext->isDependentContext()) {
20882 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
20883 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20884 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20890 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20898 Stmt *HelperValStmt =
nullptr;
20901 !
Condition->isInstantiationDependent() &&
20902 !
Condition->containsUnexpandedParameterPack()) {
20907 ValExpr =
SemaRef.MakeFullExpr(Val.
get()).get();
20911 DKind, OMPC_nocontext,
getLangOpts().getOpenMPVersion());
20912 if (CaptureRegion != OMPD_unknown &&
20913 !
SemaRef.CurContext->isDependentContext()) {
20914 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
20915 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20916 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20922 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20929 Expr *ValExpr = ThreadID;
20930 Stmt *HelperValStmt =
nullptr;
20934 DKind, OMPC_filter,
getLangOpts().getOpenMPVersion());
20935 if (CaptureRegion != OMPD_unknown &&
20936 !
SemaRef.CurContext->isDependentContext()) {
20937 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
20938 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20939 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20944 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20955 int ExtraModifier =
Data.ExtraModifier;
20956 int OriginalSharingModifier =
Data.OriginalSharingModifier;
20957 Expr *ExtraModifierExpr =
Data.ExtraModifierExpr;
20964 case OMPC_firstprivate:
20967 case OMPC_lastprivate:
20969 "Unexpected lastprivate modifier.");
20972 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
20977 case OMPC_reduction:
20979 "Unexpected lastprivate modifier.");
20983 ExtraModifier, OriginalSharingModifier),
20984 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
20985 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
20987 case OMPC_task_reduction:
20989 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
20990 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
20992 case OMPC_in_reduction:
20994 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
20995 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
20999 "Unexpected linear modifier.");
21001 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
21003 ColonLoc,
Data.StepModifierLoc, EndLoc);
21007 LParenLoc, ColonLoc, EndLoc);
21012 case OMPC_copyprivate:
21020 "Unexpected depend modifier.");
21023 ColonLoc,
Data.OmpAllMemoryLoc},
21024 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
21028 "Unexpected map modifier.");
21030 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
21031 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
21033 ExtraModifierLoc, ColonLoc, VarList, Locs);
21037 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
21038 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
21043 Data.MotionModifiers,
Data.MotionModifiersLoc,
Data.IteratorExpr,
21044 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId, ColonLoc,
21047 case OMPC_use_device_ptr:
21048 assert(0 <=
Data.ExtraModifier &&
21050 "Unexpected use_device_ptr fallback modifier.");
21054 Data.ExtraModifierLoc);
21056 case OMPC_use_device_addr:
21059 case OMPC_is_device_ptr:
21062 case OMPC_has_device_addr:
21065 case OMPC_allocate: {
21069 if (!
Data.AllocClauseModifiers.empty()) {
21070 assert(
Data.AllocClauseModifiers.size() <= 2 &&
21071 "More allocate modifiers than expected");
21072 Modifier1 =
Data.AllocClauseModifiers[0];
21073 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
21074 if (
Data.AllocClauseModifiers.size() == 2) {
21075 Modifier2 =
Data.AllocClauseModifiers[1];
21076 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
21080 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
21081 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
21085 case OMPC_nontemporal:
21088 case OMPC_inclusive:
21091 case OMPC_exclusive:
21094 case OMPC_affinity:
21096 Data.DepModOrTailExpr, VarList);
21098 case OMPC_doacross:
21101 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
21103 case OMPC_num_teams:
21105 "Unexpected num_teams modifier.");
21109 Data.ExtraModifierExprArray[0],
Data.ExtraModifierLocArray[0],
21111 Data.ExtraModifierExprArray[1],
Data.ExtraModifierLocArray[1], StartLoc,
21112 LParenLoc, EndLoc);
21114 case OMPC_thread_limit:
21116 "Unexpected thread_limit modifier.");
21119 ExtraModifierExpr, ExtraModifierLoc, StartLoc, LParenLoc, EndLoc);
21121 case OMPC_num_threads:
21122 assert(0 <=
Data.ExtraModifierArray[0] &&
21124 0 <=
Data.ExtraModifierArray[1] &&
21126 "Unexpected num_threads modifier.");
21130 Data.ExtraModifierLocArray[0],
21132 Data.ExtraModifierExprArray[1],
Data.ExtraModifierLocArray[1], StartLoc,
21133 LParenLoc, EndLoc);
21142 case OMPC_allocator:
21143 case OMPC_collapse:
21145 case OMPC_proc_bind:
21146 case OMPC_schedule:
21150 case OMPC_mergeable:
21151 case OMPC_threadprivate:
21152 case OMPC_groupprivate:
21166 case OMPC_priority:
21167 case OMPC_grainsize:
21169 case OMPC_num_tasks:
21171 case OMPC_dist_schedule:
21172 case OMPC_defaultmap:
21175 case OMPC_unified_address:
21176 case OMPC_unified_shared_memory:
21177 case OMPC_reverse_offload:
21178 case OMPC_dynamic_allocators:
21179 case OMPC_atomic_default_mem_order:
21180 case OMPC_self_maps:
21181 case OMPC_device_type:
21185 case OMPC_severity:
21188 case OMPC_novariants:
21189 case OMPC_nocontext:
21191 case OMPC_uses_allocators:
21195 llvm_unreachable(
"Clause is not allowed.");
21208 Res =
SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.
get());
21213 Res =
SemaRef.DefaultLvalueConversion(Res.
get());
21227 bool IsImplicitClause =
21229 for (
Expr *RefExpr : VarList) {
21230 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
21233 Expr *SimpleRefExpr = RefExpr;
21237 Vars.push_back(RefExpr);
21238 PrivateCopies.push_back(
nullptr);
21245 auto *VD = dyn_cast<VarDecl>(D);
21251 diag::err_omp_private_incomplete_type))
21253 Type =
Type.getNonReferenceType();
21273 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
21274 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
21275 Diag(ELoc, diag::err_omp_wrong_dsa)
21286 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21288 << getOpenMPDirectiveName(CurrDir, OMPVersion);
21289 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21292 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21307 CurrDir == OMPD_target) {
21309 if (
DSAStack->checkMappableExprComponentListsForDecl(
21313 ConflictKind = WhereFoundClauseKind;
21316 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21319 << getOpenMPDirectiveName(CurrDir, OMPVersion);
21339 SemaRef.ActOnUninitializedDecl(VDPrivate);
21347 if (!VD && !IsBindingDecl && !
SemaRef.CurContext->isDependentContext()) {
21348 auto *FD = dyn_cast<FieldDecl>(D);
21352 RefExpr->getExprLoc());
21356 if (!IsImplicitClause) {
21357 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
21360 (VD || IsBindingDecl ||
SemaRef.CurContext->isDependentContext())
21361 ? RefExpr->IgnoreParens()
21363 PrivateCopies.push_back(VDPrivateRefExpr);
21369 return OMPPrivateClause::Create(
getASTContext(), StartLoc, LParenLoc, EndLoc,
21370 Vars, PrivateCopies);
21381 bool IsImplicitClause =
21386 for (
Expr *RefExpr : VarList) {
21387 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
21390 Expr *SimpleRefExpr = RefExpr;
21394 Vars.push_back(RefExpr);
21395 PrivateCopies.push_back(
nullptr);
21396 Inits.push_back(
nullptr);
21402 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
21404 auto *VD = dyn_cast<VarDecl>(D);
21410 diag::err_omp_firstprivate_incomplete_type))
21412 Type =
Type.getNonReferenceType();
21422 DSAStackTy::DSAVarData TopDVar;
21423 if (!IsImplicitClause) {
21424 DSAStackTy::DSAVarData DVar =
21436 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
21438 DVar.CKind != OMPC_lastprivate) &&
21440 Diag(ELoc, diag::err_omp_wrong_dsa)
21458 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
21459 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
21460 Diag(ELoc, diag::err_omp_wrong_dsa)
21486 DVar =
DSAStack->getImplicitDSA(D,
true);
21487 if (DVar.CKind != OMPC_shared &&
21490 DVar.DKind == OMPD_unknown)) {
21491 Diag(ELoc, diag::err_omp_required_access)
21513 return C == OMPC_reduction && !AppliedToPointee;
21521 if (DVar.CKind == OMPC_reduction &&
21525 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
21526 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
21542 CurrDir == OMPD_target) {
21544 if (
DSAStack->checkMappableExprComponentListsForDecl(
21549 ConflictKind = WhereFoundClauseKind;
21552 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21555 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
21566 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21568 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
21570 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21573 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21587 if (IsBindingDecl) {
21599 (PrivateVD && !IsBindingDecl)
21608 Expr *VDInitRefExpr =
nullptr;
21613 if (IsBindingDecl && !PrivateType->
isArrayType()) {
21616 PrivateType,
".firstprivate.temp");
21621 SemaRef.AddInitializerToDecl(
21622 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
21633 ElemType,
".firstprivate.temp");
21648 ".firstprivate.temp");
21650 RefExpr->getExprLoc());
21651 SemaRef.AddInitializerToDecl(
21652 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
21656 if (IsImplicitClause) {
21657 Diag(RefExpr->getExprLoc(),
21658 diag::note_omp_task_predetermined_firstprivate_here);
21662 SemaRef.CurContext->addDecl(VDPrivate);
21665 RefExpr->getExprLoc());
21667 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
21668 if (TopDVar.CKind == OMPC_lastprivate) {
21669 Ref = TopDVar.PrivateCopy;
21670 }
else if (!IsBindingDecl) {
21671 auto *FD = dyn_cast<FieldDecl>(D);
21676 RefExpr->getExprLoc());
21680 ExprCaptures.push_back(Ref->
getDecl());
21683 if (!IsImplicitClause)
21684 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
21686 (VD || IsBindingDecl ||
SemaRef.CurContext->isDependentContext())
21687 ? RefExpr->IgnoreParens()
21689 PrivateCopies.push_back(VDPrivateRefExpr);
21690 Inits.push_back(VDInitRefExpr);
21696 return OMPFirstprivateClause::Create(
21706 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
21707 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
21720 for (
Expr *RefExpr : VarList) {
21721 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
21724 Expr *SimpleRefExpr = RefExpr;
21728 Vars.push_back(RefExpr);
21729 SrcExprs.push_back(
nullptr);
21730 DstExprs.push_back(
nullptr);
21731 AssignmentOps.push_back(
nullptr);
21738 auto *VD = dyn_cast<VarDecl>(D);
21743 Diag(ELoc, diag::err_omp_unsupported_on_binding) << 1;
21752 diag::err_omp_lastprivate_incomplete_type))
21754 Type =
Type.getNonReferenceType();
21771 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
21772 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
21775 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21789 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
21790 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
21792 DVar.CKind != OMPC_firstprivate) &&
21793 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
21794 Diag(ELoc, diag::err_omp_wrong_dsa)
21807 DSAStackTy::DSAVarData TopDVar = DVar;
21811 DVar =
DSAStack->getImplicitDSA(D,
true);
21812 if (DVar.CKind != OMPC_shared) {
21813 Diag(ELoc, diag::err_omp_required_access)
21831 Type.getUnqualifiedType(),
".lastprivate.src",
21842 PseudoDstExpr, PseudoSrcExpr);
21845 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
21851 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
21852 if (TopDVar.CKind == OMPC_firstprivate) {
21853 Ref = TopDVar.PrivateCopy;
21857 ExprCaptures.push_back(Ref->
getDecl());
21860 ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
21868 SimpleRefExpr, RefRes.
get());
21871 ExprPostUpdates.push_back(
21872 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
21875 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
21878 (VD || IsBindingDecl ||
SemaRef.CurContext->isDependentContext())
21879 ? RefExpr->IgnoreParens()
21881 SrcExprs.push_back(PseudoSrcExpr);
21882 DstExprs.push_back(PseudoDstExpr);
21883 AssignmentOps.push_back(AssignmentOp.
get());
21889 return OMPLastprivateClause::Create(
21890 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
21891 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
21901 for (
Expr *RefExpr : VarList) {
21902 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
21905 Expr *SimpleRefExpr = RefExpr;
21909 Vars.push_back(RefExpr);
21915 auto *VD = dyn_cast<VarDecl>(D);
21923 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
21924 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
21926 Diag(ELoc, diag::err_omp_wrong_dsa)
21935 !
SemaRef.CurContext->isDependentContext())
21937 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
21938 Vars.push_back((VD || !Ref ||
SemaRef.CurContext->isDependentContext())
21939 ? RefExpr->IgnoreParens()
21946 return OMPSharedClause::Create(
getASTContext(), StartLoc, LParenLoc, EndLoc,
21951class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
21956 if (
auto *VD = dyn_cast<VarDecl>(E->
getDecl())) {
21957 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
21958 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
21960 if (DVar.CKind != OMPC_unknown)
21962 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
21969 return DVarPrivate.CKind != OMPC_unknown;
21973 bool VisitStmt(Stmt *S) {
21974 for (Stmt *Child : S->
children()) {
21975 if (Child && Visit(Child))
21980 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
21987class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
21988 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
21989 ValueDecl *
Field =
nullptr;
21990 DeclRefExpr *CapturedExpr =
nullptr;
21993 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
21994 : BaseTransform(SemaRef),
Field(FieldDecl), CapturedExpr(
nullptr) {}
21996 ExprResult TransformMemberExpr(MemberExpr *E) {
21999 CapturedExpr =
buildCapture(SemaRef, Field, E,
false);
22000 return CapturedExpr;
22002 return BaseTransform::TransformMemberExpr(E);
22004 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
22008template <
typename T,
typename U>
22011 for (
U &
Set : Lookups) {
22012 for (
auto *D :
Set) {
22023 for (
auto *RD : D->
redecls()) {
22046 AssociatedClasses);
22059 for (
auto *NS : AssociatedNamespaces) {
22072 for (
auto *D : R) {
22073 auto *Underlying = D;
22074 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
22075 Underlying = USD->getTargetDecl();
22085 if (
auto *USD = dyn_cast<UsingShadowDecl>(D))
22086 Underlying = USD->getTargetDecl();
22088 Lookups.emplace_back();
22089 Lookups.back().addDecl(Underlying);
22113 Lookups.emplace_back();
22114 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22117 }
else if (
auto *ULE =
22118 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
22120 Decl *PrevD =
nullptr;
22124 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
22125 Lookups.back().addDecl(DRD);
22133 return !D->isInvalidDecl() &&
22134 (D->getType()->isDependentType() ||
22135 D->getType()->isInstantiationDependentType() ||
22136 D->getType()->containsUnexpandedParameterPack());
22149 true, ResSet.
begin(), ResSet.
end(),
false,
22172 if (IsComplete || RD->isBeingDefined()) {
22175 if (Lookup.
empty()) {
22176 Lookups.emplace_back();
22177 Lookups.back().append(Lookup.
begin(), Lookup.
end());
22219 if (ReductionIdScopeSpec.
isSet()) {
22220 SemaRef.
Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
22229struct ReductionData {
22231 SmallVector<Expr *, 8> Vars;
22235 SmallVector<Expr *, 8> LHSs;
22237 SmallVector<Expr *, 8> RHSs;
22239 SmallVector<Expr *, 8> ReductionOps;
22241 SmallVector<Expr *, 8> InscanCopyOps;
22243 SmallVector<Expr *, 8> InscanCopyArrayTemps;
22245 SmallVector<Expr *, 8> InscanCopyArrayElems;
22248 SmallVector<Expr *, 8> TaskgroupDescriptors;
22250 SmallVector<Decl *, 4> ExprCaptures;
22252 SmallVector<Expr *, 4> ExprPostUpdates;
22254 unsigned RedModifier = 0;
22256 unsigned OrigSharingModifier = 0;
22258 SmallVector<bool, 8> IsPrivateVarReduction;
22259 ReductionData() =
delete;
22261 ReductionData(
unsigned Size,
unsigned Modifier = 0,
unsigned OrgModifier = 0)
22262 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
22263 Vars.reserve(Size);
22265 LHSs.reserve(Size);
22266 RHSs.reserve(Size);
22267 ReductionOps.reserve(Size);
22268 IsPrivateVarReduction.reserve(Size);
22269 if (RedModifier == OMPC_REDUCTION_inscan) {
22270 InscanCopyOps.reserve(Size);
22271 InscanCopyArrayTemps.reserve(Size);
22272 InscanCopyArrayElems.reserve(Size);
22274 TaskgroupDescriptors.reserve(Size);
22275 ExprCaptures.reserve(Size);
22276 ExprPostUpdates.reserve(Size);
22280 void push(Expr *Item, Expr *ReductionOp) {
22281 Vars.emplace_back(Item);
22283 LHSs.emplace_back(
nullptr);
22284 RHSs.emplace_back(
nullptr);
22285 ReductionOps.emplace_back(ReductionOp);
22286 IsPrivateVarReduction.emplace_back(
false);
22287 TaskgroupDescriptors.emplace_back(
nullptr);
22288 if (RedModifier == OMPC_REDUCTION_inscan) {
22289 InscanCopyOps.push_back(
nullptr);
22290 InscanCopyArrayTemps.push_back(
nullptr);
22291 InscanCopyArrayElems.push_back(
nullptr);
22295 void push(Expr *Item, Expr *
Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
22296 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
22297 Expr *CopyArrayElem,
bool IsPrivate) {
22298 Vars.emplace_back(Item);
22300 LHSs.emplace_back(LHS);
22301 RHSs.emplace_back(RHS);
22302 ReductionOps.emplace_back(ReductionOp);
22303 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
22304 if (RedModifier == OMPC_REDUCTION_inscan) {
22305 InscanCopyOps.push_back(CopyOp);
22306 InscanCopyArrayTemps.push_back(CopyArrayTemp);
22307 InscanCopyArrayElems.push_back(CopyArrayElem);
22309 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
22310 CopyArrayElem ==
nullptr &&
22311 "Copy operation must be used for inscan reductions only.");
22313 IsPrivateVarReduction.emplace_back(IsPrivate);
22322 if (Length ==
nullptr) {
22329 SingleElement =
true;
22330 ArraySizes.push_back(llvm::APSInt::get(1));
22333 if (!Length->EvaluateAsInt(
Result, Context))
22336 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
22337 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
22338 ArraySizes.push_back(ConstantLengthValue);
22346 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
22347 Length = TempOASE->getLength();
22348 if (Length ==
nullptr) {
22355 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
22356 ArraySizes.push_back(ConstantOne);
22359 if (!Length->EvaluateAsInt(
Result, Context))
22362 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
22363 if (ConstantLengthValue.getSExtValue() != 1)
22366 ArraySizes.push_back(ConstantLengthValue);
22368 Base = TempOASE->getBase()->IgnoreParenImpCasts();
22372 if (!SingleElement) {
22373 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
22375 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
22376 ArraySizes.push_back(ConstantOne);
22377 Base = TempASE->getBase()->IgnoreParenImpCasts();
22389 return BO_AddAssign;
22391 return BO_MulAssign;
22393 return BO_AndAssign;
22395 return BO_OrAssign;
22397 return BO_XorAssign;
22453 case OO_Array_Delete:
22462 case OO_GreaterEqual:
22464 case OO_MinusEqual:
22466 case OO_SlashEqual:
22467 case OO_PercentEqual:
22468 case OO_CaretEqual:
22472 case OO_GreaterGreater:
22473 case OO_LessLessEqual:
22474 case OO_GreaterGreaterEqual:
22475 case OO_EqualEqual:
22476 case OO_ExclaimEqual:
22479 case OO_MinusMinus:
22485 case OO_Conditional:
22488 llvm_unreachable(
"Unexpected reduction identifier");
22491 if (II->isStr(
"max"))
22493 else if (II->isStr(
"min"))
22501 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
22502 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
22505 if (ReductionIdScopeSpec.
isValid())
22511 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
22512 bool FirstIter =
true;
22513 for (
Expr *RefExpr : VarList) {
22514 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
22522 if (!FirstIter && IR != ER)
22527 bool IsPrivate =
false;
22528 Expr *SimpleRefExpr = RefExpr;
22537 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
22538 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
22539 Expr *ReductionOp =
nullptr;
22541 (DeclareReductionRef.
isUnset() ||
22543 ReductionOp = DeclareReductionRef.
get();
22545 RD.push(RefExpr, ReductionOp);
22551 Expr *TaskgroupDescriptor =
nullptr;
22553 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
22554 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
22556 Type = ASE->getType().getNonReferenceType();
22560 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22561 Type = ATy->getElementType();
22564 Type =
Type.getNonReferenceType();
22568 auto *VD = dyn_cast<VarDecl>(D);
22570 auto *BD = dyn_cast<BindingDecl>(D);
22573 S.
Diag(ELoc, diag::err_omp_unsupported_on_binding) << 0;
22581 diag::err_omp_reduction_incomplete_type))
22587 false, ASE || OASE))
22594 if (!ASE && !OASE) {
22596 VarDecl *VDDef = VD->getDefinition();
22598 DSARefChecker Check(Stack);
22599 if (Check.Visit(VDDef->
getInit())) {
22600 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
22619 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
22620 if (DVar.CKind == OMPC_reduction) {
22621 S.
Diag(ELoc, diag::err_omp_once_referenced)
22627 if (DVar.CKind != OMPC_unknown) {
22628 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
22644 DVar = Stack->getImplicitDSA(D,
true);
22645 if (DVar.CKind != OMPC_shared) {
22646 S.
Diag(ELoc, diag::err_omp_required_access)
22660 DVar = Stack->getImplicitDSA(D,
true);
22662 IsPrivate = DVar.CKind != OMPC_shared;
22663 bool IsOrphaned =
false;
22665 IsOrphaned = ParentDir == OMPD_unknown;
22667 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
22673 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D,
false);
22674 if (DVar.CKind == OMPC_threadprivate) {
22675 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
22687 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
22688 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
22692 (DeclareReductionRef.
isUnset() ||
22694 RD.push(RefExpr, DeclareReductionRef.
get());
22696 if (RD.RedModifier == OMPC_REDUCTION_inscan)
22697 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction,
nullptr,
22698 RD.RedModifier, ASE || OASE);
22701 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
22705 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
22706 <<
Type << ReductionIdRange;
22709 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
22710 <<
Type << ReductionIdRange;
22722 if (DeclareReductionRef.
isUnset()) {
22723 if ((BOK == BO_GT || BOK == BO_LT) &&
22726 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
22729 if (!ASE && !OASE) {
22730 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22733 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22738 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
22740 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
22742 if (!ASE && !OASE) {
22743 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22746 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22753 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
22762 bool ConstantLengthOASE =
false;
22764 bool SingleElement;
22767 Context, OASE, SingleElement, ArraySizes);
22770 if (ConstantLengthOASE && !SingleElement) {
22771 for (llvm::APSInt &Size : ArraySizes)
22772 PrivateTy = Context.getConstantArrayType(PrivateTy, Size,
nullptr,
22778 if ((OASE && !ConstantLengthOASE) ||
22781 if (!Context.getTargetInfo().isVLASupported()) {
22783 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
22784 S.
Diag(ELoc, diag::note_vla_unsupported);
22787 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
22788 S.
targetDiag(ELoc, diag::note_vla_unsupported);
22796 PrivateTy = Context.getVariableArrayType(
22801 }
else if (!ASE && !OASE &&
22814 if (DeclareReductionRef.
isUsable()) {
22817 if (DRD->getInitializer()) {
22871 Type = ComplexTy->getElementType();
22873 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
22874 Context.getFloatTypeSemantics(
Type));
22878 uint64_t Size = Context.getTypeSize(
Type);
22879 QualType IntTy = Context.getIntTypeForBitwidth(Size, 0);
22880 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
22899 uint64_t Size = Context.getTypeSize(
Type);
22901 Context.getIntTypeForBitwidth(Size, IsSigned);
22902 llvm::APInt InitValue =
22903 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
22904 : llvm::APInt::getMinValue(Size)
22905 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
22906 : llvm::APInt::getMaxValue(Size);
22911 ELoc, Context.getTrivialTypeSourceInfo(
Type, ELoc), ELoc,
Init);
22917 llvm::APFloat InitValue = llvm::APFloat::getLargest(
22918 Context.getFloatTypeSemantics(
Type), BOK != BO_LT);
22948 llvm_unreachable(
"Unexpected reduction operation");
22957 }
else if (!
Init) {
22967 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
22968 <<
Type << ReductionIdRange;
22969 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22972 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22978 if (DeclareReductionRef.
isUsable()) {
22980 QualType PtrRedTy = Context.getPointerType(RedTy);
22983 if (!BasePath.empty()) {
22987 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
22990 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
22994 QualType Params[] = {PtrRedTy, PtrRedTy};
22995 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
23009 CombBOK, LHSDRE, RHSDRE);
23016 if (BOK != BO_LT && BOK != BO_GT) {
23019 BO_Assign, LHSDRE, ReductionOp.
get());
23021 auto *ConditionalOp =
new (Context)
23026 BO_Assign, LHSDRE, ConditionalOp);
23039 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
23040 if (ClauseKind == OMPC_reduction &&
23041 RD.RedModifier == OMPC_REDUCTION_inscan) {
23043 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
23053 if (Stack->getCurrentDirective() == OMPD_simd ||
23091 if (ClauseKind == OMPC_in_reduction) {
23094 const Expr *ParentReductionOp =
nullptr;
23095 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
23096 DSAStackTy::DSAVarData ParentBOKDSA =
23097 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
23099 DSAStackTy::DSAVarData ParentReductionOpDSA =
23100 Stack->getTopMostTaskgroupReductionData(
23101 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
23102 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
23103 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
23104 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
23105 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
23106 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
23107 bool EmitError =
true;
23108 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
23109 llvm::FoldingSetNodeID RedId, ParentRedId;
23110 ParentReductionOp->
Profile(ParentRedId, Context,
true);
23111 DeclareReductionRef.
get()->
Profile(RedId, Context,
23113 EmitError = RedId != ParentRedId;
23117 diag::err_omp_reduction_identifier_mismatch)
23118 << ReductionIdRange << RefExpr->getSourceRange();
23120 diag::note_omp_previous_reduction_identifier)
23122 << (IsParentBOK ? ParentBOKDSA.RefExpr
23123 : ParentReductionOpDSA.RefExpr)
23124 ->getSourceRange();
23128 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
23136 TransformExprToCaptures RebuildToCapture(S, D);
23138 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
23139 Ref = RebuildToCapture.getCapturedExpr();
23141 VarsExpr = Ref =
buildCapture(S, D, SimpleRefExpr,
false);
23144 RD.ExprCaptures.emplace_back(Ref->
getDecl());
23150 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
23155 Stack->getCurrentDirective() == OMPD_taskgroup) {
23156 S.
Diag(RefExpr->getExprLoc(),
23157 diag::err_omp_reduction_non_addressable_expression)
23158 << RefExpr->getSourceRange();
23161 RD.ExprPostUpdates.emplace_back(
23168 unsigned Modifier = RD.RedModifier;
23171 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
23172 Modifier = OMPC_REDUCTION_task;
23173 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
23175 if (Modifier == OMPC_REDUCTION_task &&
23176 (CurrDir == OMPD_taskgroup ||
23180 if (DeclareReductionRef.
isUsable())
23181 Stack->addTaskgroupReductionData(D, ReductionIdRange,
23182 DeclareReductionRef.
get());
23184 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
23186 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
23187 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
23188 TempArrayElem.
get(), IsPrivate);
23190 return RD.Vars.empty();
23206 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
23217 if (Modifier == OMPC_REDUCTION_inscan &&
23218 (
DSAStack->getCurrentDirective() != OMPD_for &&
23219 DSAStack->getCurrentDirective() != OMPD_for_simd &&
23220 DSAStack->getCurrentDirective() != OMPD_simd &&
23221 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
23222 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
23223 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
23226 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
23228 StartLoc, LParenLoc, ColonLoc, EndLoc,
23229 ReductionIdScopeSpec, ReductionId,
23230 UnresolvedReductions, RD))
23233 return OMPReductionClause::Create(
23234 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
23237 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
23238 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
23241 OriginalSharingModifier);
23249 ReductionData RD(VarList.size());
23251 VarList, StartLoc, LParenLoc, ColonLoc,
23252 EndLoc, ReductionIdScopeSpec, ReductionId,
23253 UnresolvedReductions, RD))
23256 return OMPTaskReductionClause::Create(
23257 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
23259 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
23269 ReductionData RD(VarList.size());
23271 StartLoc, LParenLoc, ColonLoc, EndLoc,
23272 ReductionIdScopeSpec, ReductionId,
23273 UnresolvedReductions, RD))
23276 return OMPInReductionClause::Create(
23277 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
23279 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
23288 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
23298 const auto *VD = dyn_cast_or_null<VarDecl>(D);
23301 diag::err_omp_linear_incomplete_type))
23303 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
23305 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
23309 Type =
Type.getNonReferenceType();
23316 if (!IsDeclareSimd &&
23321 Type =
Type.getUnqualifiedType().getCanonicalType();
23322 const auto *Ty =
Type.getTypePtrOrNull();
23323 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
23324 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
23325 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
23327 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
23330 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
23353 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
23355 LinKind = OMPC_LINEAR_val;
23356 for (
Expr *RefExpr : VarList) {
23357 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
23360 Expr *SimpleRefExpr = RefExpr;
23364 Vars.push_back(RefExpr);
23366 Inits.push_back(
nullptr);
23376 Diag(ELoc, diag::err_omp_unsupported_on_binding) << 2;
23382 auto *VD = dyn_cast<VarDecl>(D);
23388 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
23389 if (DVar.RefExpr) {
23390 Diag(ELoc, diag::err_omp_wrong_dsa)
23399 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
23411 if (!VD && !IsBindingDecl && !
SemaRef.CurContext->isDependentContext()) {
23414 ExprCaptures.push_back(Ref->
getDecl());
23421 SimpleRefExpr, RefRes.
get());
23424 ExprPostUpdates.push_back(
23425 SemaRef.IgnoredValueConversions(PostUpdateRes.
get()).get());
23432 Expr *InitExpr = Ref ? Ref : SimpleRefExpr;
23433 SemaRef.AddInitializerToDecl(
23434 Init,
SemaRef.DefaultLvalueConversion(InitExpr).get(),
23438 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
23440 (VD || IsBindingDecl ||
SemaRef.CurContext->isDependentContext())
23441 ? RefExpr->IgnoreParens()
23444 Inits.push_back(InitRef);
23450 Expr *StepExpr = Step;
23451 Expr *CalcStepExpr =
nullptr;
23459 StepExpr = Val.
get();
23467 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.
get(), StepExpr);
23469 SemaRef.ActOnFinishFullExpr(CalcStep.
get(),
false);
23473 if (std::optional<llvm::APSInt>
Result =
23475 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
23476 Diag(StepLoc, diag::warn_omp_linear_step_zero)
23477 << Vars[0] << (Vars.size() > 1);
23481 CalcStepExpr = CalcStep.
get();
23485 return OMPLinearClause::Create(
getASTContext(), StartLoc, LParenLoc, LinKind,
23486 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
23493 Expr *NumIterations,
Sema &SemaRef,
23494 Scope *S, DSAStackTy *Stack) {
23499 Expr *Step = Clause.getStep();
23500 Expr *CalcStep = Clause.getCalcStep();
23507 bool HasErrors =
false;
23508 auto CurInit = Clause.inits().begin();
23509 auto CurPrivate = Clause.privates().begin();
23510 for (
Expr *RefExpr : Clause.varlist()) {
23513 Expr *SimpleRefExpr = RefExpr;
23514 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23516 if (Res.second || !D) {
23518 Finals.push_back(
nullptr);
23522 auto &&Info = Stack->isLoopControlVariable(D);
23529 diag::err_omp_linear_distribute_var_non_loop_iteration);
23531 Finals.push_back(
nullptr);
23535 Expr *InitExpr = *CurInit;
23542 CapturedRef = SimpleRefExpr;
23546 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
23554 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
23565 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
23568 Final = *CurPrivate;
23572 if (!
Update.isUsable() || !Final.isUsable()) {
23574 Finals.push_back(
nullptr);
23575 UsedExprs.push_back(
nullptr);
23579 Finals.push_back(Final.get());
23581 UsedExprs.push_back(SimpleRefExpr);
23586 if (
Expr *S = Clause.getStep())
23587 UsedExprs.push_back(S);
23589 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(),
nullptr);
23591 Clause.setFinals(Finals);
23592 Clause.setUsedExprs(UsedExprs);
23600 for (
Expr *RefExpr : VarList) {
23601 assert(RefExpr &&
"NULL expr in OpenMP aligned clause.");
23604 Expr *SimpleRefExpr = RefExpr;
23608 Vars.push_back(RefExpr);
23615 auto *VD = dyn_cast<VarDecl>(D);
23623 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
23625 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
23628 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
23635 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
23636 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23638 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23647 .DefaultFunctionArrayConversion(
23648 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
23657 if (Alignment !=
nullptr) {
23662 Alignment = AlignResult.
get();
23668 ColonLoc, EndLoc, Vars, Alignment);
23679 for (
Expr *RefExpr : VarList) {
23680 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
23683 Vars.push_back(RefExpr);
23684 SrcExprs.push_back(
nullptr);
23685 DstExprs.push_back(
nullptr);
23686 AssignmentOps.push_back(
nullptr);
23695 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
23697 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
23698 << 0 << RefExpr->getSourceRange();
23702 Decl *D = DE->getDecl();
23708 Vars.push_back(DE);
23709 SrcExprs.push_back(
nullptr);
23710 DstExprs.push_back(
nullptr);
23711 AssignmentOps.push_back(
nullptr);
23717 if (!
DSAStack->isThreadPrivate(VD)) {
23719 Diag(ELoc, diag::err_omp_required_access)
23721 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
23744 SemaRef.BuildBinOp(
nullptr, DE->getExprLoc(), BO_Assign,
23745 PseudoDstExpr, PseudoSrcExpr);
23754 DSAStack->addDSA(VD, DE, OMPC_copyin);
23755 Vars.push_back(DE);
23756 SrcExprs.push_back(PseudoSrcExpr);
23757 DstExprs.push_back(PseudoDstExpr);
23758 AssignmentOps.push_back(AssignmentOp.
get());
23765 Vars, SrcExprs, DstExprs, AssignmentOps);
23776 for (
Expr *RefExpr : VarList) {
23777 assert(RefExpr &&
"NULL expr in OpenMP copyprivate clause.");
23780 Expr *SimpleRefExpr = RefExpr;
23784 Vars.push_back(RefExpr);
23785 SrcExprs.push_back(
nullptr);
23786 DstExprs.push_back(
nullptr);
23787 AssignmentOps.push_back(
nullptr);
23794 auto *VD = dyn_cast<VarDecl>(D);
23799 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
23800 DSAStackTy::DSAVarData DVar =
23802 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
23804 Diag(ELoc, diag::err_omp_wrong_dsa)
23814 if (DVar.CKind == OMPC_unknown) {
23815 DVar =
DSAStack->getImplicitDSA(D,
false);
23817 const bool IsShared = DVar.CKind == OMPC_shared;
23821 Diag(ELoc, diag::err_omp_required_access)
23823 <<
"threadprivate or private in the enclosing context";
23834 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
23836 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
23838 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
23841 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
23862 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
23865 AssignmentOp =
SemaRef.ActOnFinishFullExpr(AssignmentOp.
get(), ELoc,
23873 assert(VD || IsBindingDecl ||
SemaRef.CurContext->isDependentContext() ||
23876 (VD || IsBindingDecl ||
SemaRef.CurContext->isDependentContext())
23877 ? RefExpr->IgnoreParens()
23879 SrcExprs.push_back(PseudoSrcExpr);
23880 DstExprs.push_back(PseudoDstExpr);
23881 AssignmentOps.push_back(AssignmentOp.
get());
23888 EndLoc, Vars, SrcExprs, DstExprs,
23896 if (VarList.empty())
23905 bool Diagnose =
true) {
23906 QualType OMPDependT = Stack->getOMPDependT();
23907 if (!OMPDependT.
isNull())
23913 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
23916 Stack->setOMPDependT(PT.
get());
23937 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
23942 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
23952struct DoacrossDataInfoTy {
23956 DSAStackTy::OperatorOffsetTy OpsOffs;
23958 llvm::APSInt TotalDepCount;
23961static DoacrossDataInfoTy
23967 DSAStackTy::OperatorOffsetTy OpsOffs;
23968 llvm::APSInt DepCounter(32);
23969 llvm::APSInt TotalDepCount(32);
23971 if (
const Expr *OrderedCountExpr =
23972 Stack->getParentOrderedRegionParam().first) {
23973 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
23974 TotalDepCount.setIsUnsigned(
true);
23977 for (
Expr *RefExpr : VarList) {
23978 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
23981 Vars.push_back(RefExpr);
23988 if (Stack->getParentOrderedRegionParam().first &&
23989 DepCounter >= TotalDepCount) {
23990 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
24004 Vars.push_back(RefExpr);
24011 Expr *RHS =
nullptr;
24012 if (
auto *BO = dyn_cast<BinaryOperator>(
SimpleExpr)) {
24014 OOLoc = BO->getOperatorLoc();
24017 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
SimpleExpr)) {
24018 OOK = OCE->getOperator();
24019 OOLoc = OCE->getOperatorLoc();
24022 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
SimpleExpr)) {
24023 OOK = MCE->getMethodDecl()
24026 .getCXXOverloadedOperator();
24027 OOLoc = MCE->getCallee()->getExprLoc();
24036 Vars.push_back(RefExpr);
24042 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
24043 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
24049 RHS, OMPC_depend,
false);
24054 Stack->getParentOrderedRegionParam().first &&
24055 DepCounter != Stack->isParentLoopControlVariable(D).first) {
24057 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
24059 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
24062 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
24066 OpsOffs.emplace_back(RHS, OOK);
24068 Vars.push_back(RefExpr->IgnoreParenImpCasts());
24071 TotalDepCount > VarList.size() &&
24072 Stack->getParentOrderedRegionParam().first &&
24073 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
24074 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
24075 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
24077 return {Vars, OpsOffs, TotalDepCount};
24086 if (
DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
24087 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
24088 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24092 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
24093 DepKind == OMPC_DEPEND_mutexinoutset) {
24094 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
24097 if ((
DSAStack->getCurrentDirective() != OMPD_ordered_standalone ||
24098 DSAStack->getCurrentDirective() == OMPD_depobj) &&
24100 DepKind == OMPC_DEPEND_sink ||
24102 DSAStack->getCurrentDirective() == OMPD_depobj) &&
24103 DepKind == OMPC_DEPEND_depobj))) {
24105 OMPC_DEPEND_outallmemory,
24106 OMPC_DEPEND_inoutallmemory};
24108 DSAStack->getCurrentDirective() == OMPD_depobj)
24109 Except.push_back(OMPC_DEPEND_depobj);
24111 Except.push_back(OMPC_DEPEND_inoutset);
24113 ?
"depend modifier(iterator) or "
24115 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24123 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
24125 diag::err_omp_depend_sink_source_with_modifier);
24130 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
24133 DSAStackTy::OperatorOffsetTy OpsOffs;
24134 llvm::APSInt TotalDepCount(32);
24136 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
24139 Vars = VarOffset.Vars;
24140 OpsOffs = VarOffset.OpsOffs;
24141 TotalDepCount = VarOffset.TotalDepCount;
24143 for (
Expr *RefExpr : VarList) {
24144 assert(RefExpr &&
"NULL expr in OpenMP depend clause.");
24147 Vars.push_back(RefExpr);
24153 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
24154 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
24155 if (OMPDependTFound)
24157 DepKind == OMPC_DEPEND_depobj);
24158 if (DepKind == OMPC_DEPEND_depobj) {
24162 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
24163 !RefExpr->isInstantiationDependent() &&
24164 !RefExpr->containsUnexpandedParameterPack() &&
24165 (OMPDependTFound &&
24167 DSAStack->getOMPDependT(), RefExpr->getType()))) {
24168 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
24169 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
24172 if (!RefExpr->isLValue()) {
24173 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
24174 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
24182 const auto *OASE = dyn_cast<ArraySectionExpr>(
SimpleExpr);
24186 if (BaseType.isNull())
24188 if (
const auto *ATy = BaseType->getAsArrayTypeUnsafe())
24189 ExprTy = ATy->getElementType();
24191 ExprTy = BaseType->getPointeeType();
24192 if (BaseType.isNull() || ExprTy.isNull())
24194 ExprTy = ExprTy.getNonReferenceType();
24195 const Expr *Length = OASE->getLength();
24197 if (Length && !Length->isValueDependent() &&
24199 Result.Val.getInt().isZero()) {
24201 diag::err_omp_depend_zero_length_array_section_not_allowed)
24211 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
24212 !RefExpr->isInstantiationDependent() &&
24213 !RefExpr->containsUnexpandedParameterPack() &&
24214 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
24215 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
24216 ExprTy.getTypePtr()))) {
24217 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24220 << RefExpr->getSourceRange();
24224 auto *ASE = dyn_cast<ArraySubscriptExpr>(
SimpleExpr);
24225 if (ASE && !ASE->getBase()->isTypeDependent() &&
24228 .getNonReferenceType()
24229 ->isPointerType() &&
24230 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
24231 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24234 << RefExpr->getSourceRange();
24241 Res =
SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
24242 RefExpr->IgnoreParenImpCasts());
24246 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24249 << RefExpr->getSourceRange();
24254 Vars.push_back(RefExpr->IgnoreParenImpCasts());
24258 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
24259 DepKind != OMPC_DEPEND_outallmemory &&
24260 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
24265 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
24266 TotalDepCount.getZExtValue());
24267 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
24268 DSAStack->isParentOrderedRegion())
24269 DSAStack->addDoacrossDependClause(
C, OpsOffs);
24278 "Unexpected device modifier in OpenMP < 50.");
24280 bool ErrorFound =
false;
24282 std::string Values =
24284 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24290 Stmt *HelperValStmt =
nullptr;
24302 if (
Value.isInvalid()) {
24305 ValExpr =
Value.get();
24306 if (std::optional<llvm::APSInt>
Result =
24309 Diag(Loc, diag::err_omp_device_expression_invalid)
24327 if (Modifier == OMPC_DEVICE_ancestor) {
24328 if (!
DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
24331 diag::err_omp_device_ancestor_without_requires_reverse_offload);
24338 DKind, OMPC_device,
getLangOpts().getOpenMPVersion());
24339 if (CaptureRegion != OMPD_unknown &&
24340 !
SemaRef.CurContext->isDependentContext()) {
24341 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
24342 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24343 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
24348 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
24349 LParenLoc, ModifierLoc, EndLoc);
24354 bool FullCheck =
true) {
24359 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
24369 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
24375 (OASE && OASE->getColonLocFirst().isInvalid())) {
24376 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
24377 return ATy->getSExtSize() != 1;
24382 assert(OASE &&
"Expecting array section if not an array subscript.");
24383 const Expr *LowerBound = OASE->getLowerBound();
24384 const Expr *Length = OASE->getLength();
24393 llvm::APSInt ConstLowerBound =
Result.Val.getInt();
24394 if (ConstLowerBound.getSExtValue())
24409 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
24417 llvm::APSInt ConstLength =
Result.Val.getInt();
24418 return CATy->getSExtSize() != ConstLength.getSExtValue();
24427 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
24432 (OASE && OASE->getColonLocFirst().isInvalid()))
24435 assert(OASE &&
"Expecting array section if not an array subscript.");
24436 const Expr *Length = OASE->getLength();
24442 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
24443 return ATy->getSExtSize() != 1;
24453 llvm::APSInt ConstLength =
Result.Val.getInt();
24454 return ConstLength.getSExtValue() != 1;
24493class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
24498 bool IsNonContiguous =
false;
24499 bool NoDiagnose =
false;
24500 const Expr *RelevantExpr =
nullptr;
24501 bool AllowUnitySizeArraySection =
true;
24502 bool AllowWholeSizeArraySection =
true;
24503 bool AllowAnotherPtr =
true;
24504 SourceLocation ELoc;
24505 SourceRange ERange;
24507 void emitErrorMsg() {
24509 if (SemaRef.getLangOpts().OpenMP < 50) {
24511 diag::err_omp_expected_named_var_member_or_array_expression)
24514 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
24520 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
24521 ValueDecl *D = DRE->
getDecl();
24531 if (
auto *BD = dyn_cast<BindingDecl>(D)) {
24537 if (
auto *ME = dyn_cast_or_null<MemberExpr>(BindingExpr)) {
24545 .BuildDeclarationNameExpr(
24553 SemaRef.Context, BaseExpr,
false, ME->getOperatorLoc(),
24554 ME->getQualifierLoc(), ME->getTemplateKeywordLoc(),
24555 ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(),
24556 nullptr, ME->getType(), ME->getValueKind(),
24557 ME->getObjectKind(), ME->isNonOdrUse());
24563 if (
auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(BindingExpr)) {
24566 .BuildDeclarationNameExpr(
24571 E =
new (SemaRef.Context) ArraySubscriptExpr(
24572 BaseExpr, ASE->getIdx(), ASE->getType(), ASE->getValueKind(),
24573 ASE->getObjectKind(), ASE->getRBracketLoc());
24579 diag::err_omp_unsupported_structured_binding_init)
24584 else if (
auto *DD = dyn_cast<DecompositionDecl>(D)) {
24585 if (
const VarDecl *OrigVar =
24586 getOriginalVarOrDiagnose(SemaRef, DD, DRE->
getExprLoc())) {
24587 D =
const_cast<VarDecl *
>(OrigVar);
24602 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
24605 Components.emplace_back(E, D, IsNonContiguous);
24609 bool VisitMemberExpr(MemberExpr *ME) {
24614 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
24623 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
24639 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
24659 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
24663 return RelevantExpr || Visit(E);
24673 AllowUnitySizeArraySection =
false;
24674 AllowWholeSizeArraySection =
false;
24677 Components.emplace_back(ME, FD, IsNonContiguous);
24678 return RelevantExpr || Visit(E);
24681 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
24686 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
24690 return RelevantExpr || Visit(E);
24697 AllowWholeSizeArraySection =
false;
24700 Expr::EvalResult
Result;
24703 !
Result.Val.getInt().isZero()) {
24705 diag::err_omp_invalid_map_this_expr);
24707 diag::note_omp_invalid_subscript_on_this_ptr_map);
24709 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
24714 Components.emplace_back(AE,
nullptr, IsNonContiguous);
24716 return RelevantExpr || Visit(E);
24719 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
24722 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
24723 "Array sections cannot be implicitly mapped.");
24737 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
24747 if (AllowWholeSizeArraySection) {
24754 if (NotWhole || IsPointer)
24755 AllowWholeSizeArraySection =
false;
24756 }
else if (DKind == OMPD_target_update &&
24757 SemaRef.getLangOpts().OpenMP >= 50) {
24758 if (IsPointer && !AllowAnotherPtr)
24759 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
24762 IsNonContiguous =
true;
24763 }
else if (AllowUnitySizeArraySection && NotUnity) {
24769 diag::err_array_section_does_not_specify_contiguous_storage)
24775 AllowAnotherPtr =
false;
24777 if (
const auto *TE = dyn_cast<CXXThisExpr>(E)) {
24778 Expr::EvalResult ResultR;
24779 Expr::EvalResult ResultL;
24784 diag::err_omp_invalid_map_this_expr);
24786 diag::note_omp_invalid_length_on_this_ptr_mapping);
24790 SemaRef.getASTContext()) &&
24793 diag::err_omp_invalid_map_this_expr);
24795 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
24797 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
24802 Components.emplace_back(OASE,
nullptr,
false);
24803 return RelevantExpr || Visit(E);
24805 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
24809 Components.emplace_back(E,
nullptr, IsNonContiguous);
24811 return Visit(
Base->IgnoreParenImpCasts());
24814 bool VisitUnaryOperator(UnaryOperator *UO) {
24815 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
24820 if (!RelevantExpr) {
24822 Components.emplace_back(UO,
nullptr,
false);
24826 bool VisitBinaryOperator(BinaryOperator *BO) {
24829 Expr *PtrE =
nullptr;
24830 if (SemaRef.getLangOpts().OpenMP >= 50 && BO->
isAdditiveOp() &&
24834 if (
LE->getType()->isPointerType())
24843 Components.emplace_back(BO,
nullptr,
false);
24844 return RelevantExpr || Visit(PtrE);
24846 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
24847 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
24848 RelevantExpr = CTE;
24849 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
24852 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
24853 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
24854 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
24857 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
24863 return Visit(Source);
24865 bool VisitStmt(Stmt *) {
24869 const Expr *getFoundBase()
const {
return RelevantExpr; }
24870 explicit MapBaseChecker(
24873 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
24874 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
24875 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
24889 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
24893 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
24894 (CKind == OMPC_to || CKind == OMPC_from)) {
24895 auto CI = CurComponents.rbegin();
24896 auto CE = CurComponents.rend();
24897 for (; CI != CE; ++CI) {
24899 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
24904 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
24908 return Checker.getFoundBase();
24917 bool CurrentRegionOnly,
24928 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
24929 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
24930 "Map clause expression with unexpected base!");
24933 bool IsEnclosedByDataEnvironmentExpr =
false;
24934 const Expr *EnclosingExpr =
nullptr;
24936 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
24937 VD, CurrentRegionOnly,
24938 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
24939 ERange, CKind, &EnclosingExpr,
24943 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
24945 assert(!StackComponents.empty() &&
24946 "Map clause expression with no components!");
24947 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
24948 "Map clause expression with unexpected base!");
24952 const Expr *RE = StackComponents.front().getAssociatedExpression();
24958 auto CI = CurComponents.rbegin();
24959 auto CE = CurComponents.rend();
24960 auto SI = StackComponents.rbegin();
24961 auto SE = StackComponents.rend();
24962 for (; CI != CE && SI != SE; ++CI, ++SI) {
24967 if (CurrentRegionOnly &&
24974 SemaRef.
Diag(CI->getAssociatedExpression()->getExprLoc(),
24975 diag::err_omp_multiple_array_items_in_map_clause)
24976 << CI->getAssociatedExpression()->getSourceRange();
24977 SemaRef.
Diag(SI->getAssociatedExpression()->getExprLoc(),
24978 diag::note_used_here)
24979 << SI->getAssociatedExpression()->getSourceRange();
24984 if (CI->getAssociatedExpression()->getStmtClass() !=
24985 SI->getAssociatedExpression()->getStmtClass())
24989 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
24995 for (; SI != SE; ++SI) {
24997 if (
const auto *ASE =
24998 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
24999 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
25000 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
25001 SI->getAssociatedExpression())) {
25004 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
25005 SI->getAssociatedExpression())) {
25010 SemaRef, SI->getAssociatedExpression(),
Type))
25020 if (CI == CE && SI == SE) {
25021 if (CurrentRegionOnly) {
25022 if (CKind == OMPC_map) {
25023 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
25025 assert(CKind == OMPC_to || CKind == OMPC_from);
25026 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
25035 IsEnclosedByDataEnvironmentExpr =
true;
25040 std::prev(CI)->getAssociatedDeclaration()->getType();
25042 std::prev(CI)->getAssociatedExpression()->getExprLoc();
25061 if (CI == CE || SI == SE) {
25064 diag::err_omp_pointer_mapped_along_with_derived_section)
25070 if (CI->getAssociatedExpression()->getStmtClass() !=
25071 SI->getAssociatedExpression()->getStmtClass() ||
25072 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
25073 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
25074 assert(CI != CE && SI != SE);
25075 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
25088 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
25089 if (CKind == OMPC_map) {
25090 if (CI != CE || SI != SE) {
25094 CI != CE ? CurComponents.begin() : StackComponents.begin();
25095 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
25097 while (It != End && !It->getAssociatedDeclaration())
25098 std::advance(It, 1);
25099 assert(It != End &&
25100 "Expected at least one component with the declaration.");
25101 if (It != Begin && It->getAssociatedDeclaration()
25103 .getCanonicalType()
25104 ->isAnyPointerType()) {
25105 IsEnclosedByDataEnvironmentExpr =
false;
25106 EnclosingExpr =
nullptr;
25110 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
25112 assert(CKind == OMPC_to || CKind == OMPC_from);
25113 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
25123 if (!CurrentRegionOnly && SI != SE)
25124 EnclosingExpr = RE;
25128 IsEnclosedByDataEnvironmentExpr |=
25129 (!CurrentRegionOnly && CI != CE && SI == SE);
25134 if (CurrentRegionOnly)
25148 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
25150 diag::err_omp_original_storage_is_shared_and_does_not_contain)
25168 Expr *UnresolvedMapper,
25189 Lookups.emplace_back();
25190 Lookups.back().append(Lookup.
begin(), Lookup.
end());
25193 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
25198 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
25199 Lookups.back().addDecl(DMD);
25208 return !D->isInvalidDecl() &&
25209 (D->getType()->isDependentType() ||
25210 D->getType()->isInstantiationDependentType() ||
25211 D->getType()->containsUnexpandedParameterPack());
25222 false, URS.
begin(), URS.
end(),
false,
25230 SemaRef.
Diag(Loc, diag::err_omp_mapper_wrong_type);
25271 SemaRef.
Diag(Loc, diag::err_omp_invalid_mapper)
25281struct MappableVarListInfo {
25283 ArrayRef<Expr *> VarList;
25285 SmallVector<Expr *, 16> ProcessedVarList;
25289 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
25291 SmallVector<Expr *, 16> UDMapperList;
25293 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
25296 VarComponents.reserve(VarList.size());
25297 VarBaseDeclarations.reserve(VarList.size());
25306 const RecordDecl *RD = BaseType->getAsRecordDecl();
25316 for (
auto *FD : RD->
fields()) {
25318 MapperVarRef,
false, Range.getBegin(),
25324 SExprs.push_back(BE);
25332 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
25335 Maps.push_back(MapClause);
25336 return MapperVarRef;
25340 DSAStackTy *Stack) {
25346 const RecordDecl *RD = BaseType->getAsRecordDecl();
25355 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
25357 BaseType, MapperId, Maps,
nullptr);
25367 DMD->setMapperVarRef(MapperVarRef);
25391 Lookups.emplace_back();
25392 Lookups.back().append(Lookup.
begin(), Lookup.
end());
25399 return !D->isInvalidDecl() &&
25400 (D->getType()->isDependentType() ||
25401 D->getType()->isInstantiationDependentType() ||
25402 D->getType()->containsUnexpandedParameterPack());
25448 {CanonType,
nullptr});
25449 llvm::DenseMap<const Type *, bool> Visited;
25451 while (!Types.empty()) {
25452 auto [BaseType, CurFD] = Types.pop_back_val();
25453 while (ParentChain.back().second == 0)
25454 ParentChain.pop_back();
25455 --ParentChain.back().second;
25456 if (BaseType.isNull())
25459 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
25462 auto It = Visited.find(BaseType.getTypePtr());
25463 if (It == Visited.end()) {
25472 DefaultMapperId, BaseType);
25473 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
25479 bool FirstIter =
true;
25489 ParentChain.emplace_back(CurFD, 1);
25491 ++ParentChain.back().second;
25493 Types.emplace_back(FieldTy, FD);
25512 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
25515 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
25516 CKind == OMPC_use_device_addr) &&
25517 "Unexpected clause kind with mappable expressions!");
25526 MapperId.
setName(DeclNames.getIdentifier(
25528 MapperId.
setLoc(StartLoc);
25532 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
25533 bool UpdateUMIt =
false;
25534 Expr *UnresolvedMapper =
nullptr;
25536 bool HasHoldModifier =
25537 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
25545 for (
Expr *RE : MVLI.VarList) {
25546 assert(RE &&
"Null expr in omp to/from/map clause");
25550 if (UpdateUMIt && UMIt != UMEnd) {
25554 "Expect the size of UnresolvedMappers to match with that of VarList");
25558 UnresolvedMapper = *UMIt;
25562 if (
VE->isValueDependent() ||
VE->isTypeDependent() ||
25563 VE->isInstantiationDependent() ||
25564 VE->containsUnexpandedParameterPack()) {
25567 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25568 VE->getType().getCanonicalType(), UnresolvedMapper, ELoc);
25571 MVLI.UDMapperList.push_back(ER.
get());
25574 MVLI.ProcessedVarList.push_back(RE);
25582 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
25585 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
25593 if (
const auto *DRE = dyn_cast<DeclRefExpr>(
SimpleExpr)) {
25596 if (
const auto *B = dyn_cast<BindingDecl>(DRE->
getDecl())) {
25599 }
else if (
const auto *D =
25600 dyn_cast<DecompositionDecl>(DRE->
getDecl())) {
25606 diag::err_omp_unsupported_structured_binding_init)
25610 if (!getOriginalVarOrDiagnose(SemaRef, DD, ELoc))
25622 DSAS->getCurrentDirective(), NoDiagnose);
25626 assert(!CurComponents.empty() &&
25627 "Invalid mappable expression information.");
25629 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
25631 DSAS->addMappedClassesQualTypes(TE->getType());
25634 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25635 VE->getType().getCanonicalType(), UnresolvedMapper, ELoc);
25638 MVLI.UDMapperList.push_back(ER.
get());
25640 MVLI.ProcessedVarList.push_back(RE);
25641 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25642 MVLI.VarComponents.back().append(CurComponents.begin(),
25643 CurComponents.end());
25644 MVLI.VarBaseDeclarations.push_back(
nullptr);
25651 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
25652 assert(CurDeclaration &&
"Null decl on map clause.");
25655 "Expecting components to have associated only canonical declarations.");
25657 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
25658 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
25660 assert((VD || FD) &&
"Only variables or fields are expected here!");
25667 if (VD && DSAS->isThreadPrivate(VD)) {
25670 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
25671 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
25679 if (VD && CKind == OMPC_map) {
25680 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
25681 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
25682 if (*Res == OMPDeclareTargetDeclAttr::MT_Local) {
25685 SemaRef.
Diag(ELoc, diag::err_omp_device_local_in_clause)
25701 true, CurComponents, CKind))
25703 if (CKind == OMPC_map &&
25706 false, CurComponents, CKind))
25713 auto I = llvm::find_if(
25715 [](
const OMPClauseMappableExprCommon::MappableComponent &MC) {
25718 assert(I != CurComponents.end() &&
"Null decl on map clause.");
25721 auto *ASE = dyn_cast<ArraySubscriptExpr>(
VE->IgnoreParens());
25722 auto *OASE = dyn_cast<ArraySectionExpr>(
VE->IgnoreParens());
25723 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(
VE->IgnoreParens());
25725 Type = ASE->getType().getNonReferenceType();
25730 Type = ATy->getElementType();
25733 Type =
Type.getNonReferenceType();
25734 }
else if (OAShE) {
25748 if (CKind == OMPC_map) {
25755 if (DKind == OMPD_target_enter_data &&
25756 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
25758 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
25759 << (IsMapTypeImplicit ? 1 : 0)
25761 << getOpenMPDirectiveName(DKind, OMPVersion);
25770 if (DKind == OMPD_target_exit_data &&
25771 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
25772 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
25773 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
25774 << (IsMapTypeImplicit ? 1 : 0)
25776 << getOpenMPDirectiveName(DKind, OMPVersion);
25785 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
25787 SemaRef.
Diag(StartLoc,
25788 diag::err_omp_invalid_map_type_modifier_for_directive)
25790 OMPC_MAP_MODIFIER_ompx_hold)
25791 << getOpenMPDirectiveName(DKind, OMPVersion);
25799 if ((DKind == OMPD_target_data ||
25801 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
25802 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
25803 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
25804 << (IsMapTypeImplicit ? 1 : 0)
25806 << getOpenMPDirectiveName(DKind, OMPVersion);
25818 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
25820 DKind == OMPD_target)) {
25821 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
25823 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
25826 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
25836 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25837 Type.getCanonicalType(), UnresolvedMapper, ELoc);
25849 BaseType =
VE->getType().getCanonicalType();
25856 ElemType = ATy->getElementType();
25861 }
else if (
VE->getType()->isArrayType()) {
25862 const ArrayType *AT =
VE->getType()->getAsArrayTypeUnsafe();
25872 MVLI.UDMapperList.push_back(ER.
get());
25875 MVLI.ProcessedVarList.push_back(RE);
25879 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
25885 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25886 MVLI.VarComponents.back().append(CurComponents.begin(),
25887 CurComponents.end());
25909 BuiltinType::OMPIterator))
25911 diag::err_omp_map_modifier_not_iterator);
25914 unsigned Count = 0;
25915 for (
unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
25917 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
25918 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
25922 "Modifiers exceed the allowed number of map type modifiers");
25923 Modifiers[Count] = MapTypeModifiers[I];
25924 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
25928 MappableVarListInfo MVLI(VarList);
25934 for (
auto *E : VarList) {
25935 if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
25937 MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
25940 MapperIdScopeSpec, MapperId, UnresolvedMappers,
25941 MapType, Modifiers, IsMapTypeImplicit,
25947 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25948 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
25950 MapperId, MapType, IsMapTypeImplicit, MapLoc);
25958 if (ReductionType.
isNull())
25966 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
25971 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
25975 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
25979 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
25982 return ReductionType;
25988 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
25991 Decls.reserve(ReductionTypes.size());
25995 SemaRef.forRedeclarationInCurContext());
26000 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
26002 bool InCompoundScope =
true;
26003 if (S !=
nullptr) {
26009 SemaRef.LookupName(Lookup, S);
26010 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
26012 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
26014 while (Filter.hasNext()) {
26016 if (InCompoundScope) {
26017 UsedAsPrevious.try_emplace(PrevDecl,
false);
26019 UsedAsPrevious[D] =
true;
26021 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
26022 PrevDecl->getLocation();
26025 if (InCompoundScope) {
26026 for (
const auto &PrevData : UsedAsPrevious) {
26027 if (!PrevData.second) {
26028 PrevDRD = PrevData.first;
26033 }
else if (PrevDeclInScope !=
nullptr) {
26034 auto *PrevDRDInScope = PrevDRD =
26037 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
26038 PrevDRDInScope->getLocation();
26039 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
26040 }
while (PrevDRDInScope !=
nullptr);
26042 for (
const auto &TyData : ReductionTypes) {
26043 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
26045 if (I != PreviousRedeclTypes.end()) {
26046 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
26048 Diag(I->second, diag::note_previous_definition);
26051 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
26053 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
26055 DRD->setAccess(AS);
26056 Decls.push_back(DRD);
26058 DRD->setInvalidDecl();
26072 SemaRef.setFunctionHasBranchProtectedScope();
26073 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
26076 SemaRef.PushDeclContext(S, DRD);
26080 SemaRef.PushExpressionEvaluationContext(
26083 QualType ReductionType = DRD->getType();
26100 if (S !=
nullptr) {
26101 SemaRef.PushOnScopeChains(OmpInParm, S);
26102 SemaRef.PushOnScopeChains(OmpOutParm, S);
26104 DRD->addDecl(OmpInParm);
26105 DRD->addDecl(OmpOutParm);
26111 DRD->setCombinerData(InE, OutE);
26117 SemaRef.DiscardCleanupsInEvaluationContext();
26118 SemaRef.PopExpressionEvaluationContext();
26121 SemaRef.PopFunctionScopeInfo();
26123 if (Combiner !=
nullptr)
26124 DRD->setCombiner(Combiner);
26126 DRD->setInvalidDecl();
26135 SemaRef.setFunctionHasBranchProtectedScope();
26138 SemaRef.PushDeclContext(S, DRD);
26142 SemaRef.PushExpressionEvaluationContext(
26145 QualType ReductionType = DRD->getType();
26162 if (S !=
nullptr) {
26163 SemaRef.PushOnScopeChains(OmpPrivParm, S);
26164 SemaRef.PushOnScopeChains(OmpOrigParm, S);
26166 DRD->addDecl(OmpPrivParm);
26167 DRD->addDecl(OmpOrigParm);
26173 DRD->setInitializerData(OrigE, PrivE);
26174 return OmpPrivParm;
26183 if (
Initializer && !DRD->getDeclContext()->isDependentContext()) {
26184 QualType ReductionType = DRD->getType();
26186 if (!RD->hasTrivialDefaultConstructor())
26187 SemaRef.ActOnUninitializedDecl(OmpPrivParm);
26191 SemaRef.DiscardCleanupsInEvaluationContext();
26192 SemaRef.PopExpressionEvaluationContext();
26195 SemaRef.PopFunctionScopeInfo();
26199 }
else if (OmpPrivParm->
hasInit()) {
26200 DRD->setInitializer(OmpPrivParm->
getInit(),
26205 DRD->setInvalidDecl();
26211 for (
Decl *D : DeclReductions.
get()) {
26220 return DeclReductions;
26232 SemaRef.CheckExtraCXXDefaultArguments(D);
26235 return SemaRef.CreateParsedType(
T, TInfo);
26240 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
26243 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
26248 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
26260 SemaRef.forRedeclarationInCurContext());
26265 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
26267 bool InCompoundScope =
true;
26268 if (S !=
nullptr) {
26274 SemaRef.LookupName(Lookup, S);
26275 SemaRef.FilterLookupForScope(Lookup, DC, S,
false,
26277 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
26279 while (Filter.hasNext()) {
26281 if (InCompoundScope) {
26282 UsedAsPrevious.try_emplace(PrevDecl,
false);
26284 UsedAsPrevious[D] =
true;
26286 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
26287 PrevDecl->getLocation();
26290 if (InCompoundScope) {
26291 for (
const auto &PrevData : UsedAsPrevious) {
26292 if (!PrevData.second) {
26293 PrevDMD = PrevData.first;
26298 }
else if (PrevDeclInScope) {
26299 auto *PrevDMDInScope = PrevDMD =
26302 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
26303 PrevDMDInScope->getLocation();
26304 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
26305 }
while (PrevDMDInScope !=
nullptr);
26309 if (I != PreviousRedeclTypes.end()) {
26310 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
26311 << MapperType << Name;
26312 Diag(I->second, diag::note_previous_definition);
26320 ClausesWithImplicit);
26322 MapperType, VN, ClausesWithImplicit,
26325 SemaRef.PushOnScopeChains(DMD, S);
26328 DMD->setAccess(AS);
26330 DMD->setInvalidDecl();
26336 DMD->setMapperVarRef(MapperVarRef);
26350 SemaRef.PushOnScopeChains(VD, S,
false);
26352 DSAStack->addDeclareMapperVarRef(E);
26359 if (
DSAStack->getDeclareMapperVarRef()) {
26365 assert(!IsGlobalVar &&
"Only declare mapper handles TU-scope iterators.");
26370 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
26372 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
26385 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
26390 int Modifier,
Expr *ModifierExpr,
26394 assert(ModifierExpr &&
"Unexpected modifier expression.");
26397 Diag(ModifierLoc, diag::err_omp_modifier_requires_version)
26399 << getOpenMPClauseName(ClauseKind) <<
"6.1";
26404 ModifierExpr, ClauseKind,
true,
26409 ModifierExpr = DimsRes.
get();
26415 if (NumDims == VarList.size())
26418 Diag(VarListEndLoc, diag::err_omp_unexpected_num_exprs)
26419 << getOpenMPClauseName(ClauseKind) << NumDims << VarList.size();
26429 if (VarList.empty())
26432 for (
Expr *ValExpr : VarList) {
26445 Diag(ModifierExtraLoc, diag::err_omp_incompatible_modifiers)
26449 << getOpenMPClauseName(llvm::omp::OMPC_num_teams);
26454 if (Modifier == OMPC_NUMTEAMS_dims) {
26456 OMPC_num_teams, Modifier, ModifierExpr, ModifierLoc, VarList, EndLoc);
26459 ModifierExpr = Res.
get();
26460 }
else if (Modifier == OMPC_NUMTEAMS_lower_bound) {
26461 assert(ModifierExpr &&
"Unexpected modifier expression.");
26464 Diag(ModifierLoc, diag::err_omp_modifier_requires_version)
26466 << getOpenMPClauseName(llvm::omp::OMPC_num_teams) <<
"5.1";
26478 Expr *LowerBound = ModifierExpr;
26479 Expr *UpperBound = VarList[0];
26487 llvm::APSInt LowerVal =
26489 llvm::APSInt UpperVal =
26492 if (LowerVal > UpperVal) {
26494 diag::err_omp_num_teams_lower_bound_larger)
26503 DKind, OMPC_num_teams,
getLangOpts().getOpenMPVersion());
26504 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
26506 LParenLoc, EndLoc, VarList, Modifier,
26507 ModifierExpr, ModifierLoc,
26510 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26512 for (
Expr *ValExpr : VarList) {
26513 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
26514 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
26515 Vars.push_back(ValExpr);
26518 if (ModifierExpr) {
26519 ModifierExpr =
SemaRef.MakeFullExpr(ModifierExpr).get();
26520 ModifierExpr = tryBuildCapture(
SemaRef, ModifierExpr, Captures).get();
26525 LParenLoc, EndLoc, Vars, Modifier,
26526 ModifierExpr, ModifierLoc, PreInit);
26533 if (VarList.empty())
26536 for (
Expr *ValExpr : VarList) {
26544 if (Modifier == OMPC_THREADLIMIT_dims) {
26547 ModifierLoc, VarList, EndLoc);
26550 ModifierExpr = Res.
get();
26555 DKind, OMPC_thread_limit,
getLangOpts().getOpenMPVersion());
26556 if (CaptureRegion == OMPD_unknown ||
SemaRef.CurContext->isDependentContext())
26558 StartLoc, LParenLoc, EndLoc, VarList,
26559 Modifier, ModifierExpr, ModifierLoc,
26562 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26564 for (
Expr *ValExpr : VarList) {
26565 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
26566 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
26567 Vars.push_back(ValExpr);
26570 if (ModifierExpr) {
26571 ModifierExpr =
SemaRef.MakeFullExpr(ModifierExpr).get();
26572 ModifierExpr = tryBuildCapture(
SemaRef, ModifierExpr, Captures).get();
26577 LParenLoc, EndLoc, Vars, Modifier,
26578 ModifierExpr, ModifierLoc, PreInit);
26585 Expr *ValExpr = Priority;
26586 Stmt *HelperValStmt =
nullptr;
26592 ValExpr,
SemaRef, OMPC_priority,
26594 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
26598 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
26606 "Unexpected grainsize modifier in OpenMP < 51.");
26611 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
26616 Expr *ValExpr = Grainsize;
26617 Stmt *HelperValStmt =
nullptr;
26627 &CaptureRegion, &HelperValStmt))
26632 StartLoc, LParenLoc, ModifierLoc, EndLoc);
26640 "Unexpected num_tasks modifier in OpenMP < 51.");
26645 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
26650 Expr *ValExpr = NumTasks;
26651 Stmt *HelperValStmt =
nullptr;
26658 ValExpr,
SemaRef, OMPC_num_tasks,
26660 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
26665 StartLoc, LParenLoc, ModifierLoc, EndLoc);
26685 DSAStackTy *Stack) {
26686 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
26687 if (!OMPEventHandleT.
isNull())
26692 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
26695 Stack->setOMPEventHandleT(PT.
get());
26716 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
26726 <<
"omp_event_handle_t" << 1 << VD->
getType()
26733 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
26734 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
26753 std::string Values;
26757 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26761 Expr *ValExpr = ChunkSize;
26762 Stmt *HelperValStmt =
nullptr;
26773 ValExpr = Val.
get();
26778 if (std::optional<llvm::APSInt>
Result =
26780 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
26781 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
26782 <<
"dist_schedule" << 1
26787 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
26788 getLangOpts().getOpenMPVersion()) != OMPD_unknown &&
26789 !
SemaRef.CurContext->isDependentContext()) {
26790 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
26791 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26792 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
26800 Kind, ValExpr, HelperValStmt);
26808 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
26809 Kind != OMPC_DEFAULTMAP_scalar) {
26813 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
26815 OMPC_DEFAULTMAP_MODIFIER_tofrom);
26819 OMPC_DEFAULTMAP_scalar);
26823 Diag(Loc, diag::err_omp_unexpected_clause_value)
26831 if (!isDefaultmapKind || !isDefaultmapModifier) {
26833 ?
"'scalar', 'aggregate', 'pointer'"
26834 :
"'scalar', 'aggregate', 'pointer', 'all'";
26836 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
26837 "'firstprivate', 'none', 'default'";
26838 if (!isDefaultmapKind && isDefaultmapModifier) {
26839 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26841 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
26842 Diag(MLoc, diag::err_omp_unexpected_clause_value)
26845 Diag(MLoc, diag::err_omp_unexpected_clause_value)
26847 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26851 StringRef ModifierValue =
26853 ?
"'alloc', 'from', 'to', 'tofrom', "
26854 "'firstprivate', 'none', 'default', 'present'"
26855 :
"'storage', 'from', 'to', 'tofrom', "
26856 "'firstprivate', 'private', 'none', 'default', 'present'";
26857 if (!isDefaultmapKind && isDefaultmapModifier) {
26858 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26860 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
26861 Diag(MLoc, diag::err_omp_unexpected_clause_value)
26864 Diag(MLoc, diag::err_omp_unexpected_clause_value)
26866 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26876 if (
DSAStack->checkDefaultmapCategory(Kind)) {
26877 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
26883 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
26884 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
26885 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
26887 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
26904 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
26910 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
26912 DeclareTargetNesting.push_back(DTCI);
26918 assert(!DeclareTargetNesting.empty() &&
26919 "check isInOpenMPDeclareTargetContext() first!");
26920 return DeclareTargetNesting.pop_back_val();
26930 if (DeclareTargetNesting.empty())
26934 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
26935 << getOpenMPDirectiveName(DTCI.
Kind, OMPVersion);
26941 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
26950 VarOrFuncDeclFilterCCC CCC(
SemaRef);
26954 SemaRef.diagnoseTypo(Corrected,
26955 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
26979 "Expected variable, function or function template.");
26981 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
26983 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
26984 !VD->isStaticDataMember()) {
26985 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
26994 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
26998 Diag(Loc, diag::warn_hip_omp_target_directives);
27002 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
27003 DTCI.
DT == OMPDeclareTargetDeclAttr::DT_Host) {
27004 Diag(Loc, diag::err_omp_declare_target_local_host_only);
27009 const unsigned Level = -1;
27012 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
27013 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
27014 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
27015 (*ActiveAttr)->getLevel() == Level) {
27016 Diag(Loc, diag::err_omp_device_type_mismatch)
27017 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
27018 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
27019 (*ActiveAttr)->getDevType());
27022 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
27023 (*ActiveAttr)->getLevel() == Level) {
27024 Diag(Loc, diag::err_omp_declare_target_var_in_both_clauses)
27026 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
27027 (*ActiveAttr)->getMapType())
27028 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(MT);
27032 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
27035 Expr *IndirectE =
nullptr;
27036 bool IsIndirect =
false;
27046 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
27047 DT == OMPDeclareTargetDeclAttr::DT_NoHost) {
27048 Diag(Loc, diag::warn_omp_declare_target_local_nohost);
27049 DT = OMPDeclareTargetDeclAttr::DT_Any;
27052 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
27057 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
27059 if (
auto *VD = dyn_cast<VarDecl>(ND);
27061 VD->hasGlobalStorage())
27070 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
27071 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
27072 if (SemaRef.
LangOpts.OpenMP >= 50 &&
27075 VD->hasGlobalStorage()) {
27076 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
27077 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
27078 *
MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
27085 diag::err_omp_lambda_capture_in_declare_target_not_to);
27086 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
27093 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
27094 SemaRef.
Diag(SL, diag::note_used_here) << SR;
27098 Sema &SemaRef, DSAStackTy *Stack,
27100 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
27111 if (
auto *VD = dyn_cast<VarDecl>(D)) {
27113 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
27114 !VD->isStaticDataMember())
27118 if (
DSAStack->isThreadPrivate(VD)) {
27119 Diag(SL, diag::err_omp_threadprivate_in_target);
27124 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
27125 D = FTD->getTemplatedDecl();
27126 if (
auto *FD = dyn_cast<FunctionDecl>(D)) {
27127 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
27128 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
27129 if (IdLoc.
isValid() && Res &&
27130 (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
27131 *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
27132 Diag(IdLoc, diag::err_omp_function_in_target_clause_list)
27133 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(*Res);
27138 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
27148 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
27149 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
27150 unsigned Level = DeclareTargetNesting.size();
27151 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
27154 Expr *IndirectE =
nullptr;
27155 bool IsIndirect =
false;
27161 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
27163 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
27164 : OMPDeclareTargetDeclAttr::MT_To,
27165 DTCI.
DT, IndirectE, IsIndirect, Level,
27169 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
27189 if (
auto *VD = dyn_cast<VarDecl>(Node->
getDecl())) {
27191 DeclVector.push_back(VD);
27196 for (
auto *Child : Ex->
children()) {
27205 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
27207 llvm::SmallDenseSet<Decl *> Visited;
27208 while (!DeclVector.empty()) {
27209 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
27210 if (!Visited.insert(TargetVarDecl).second)
27213 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
27243 unsigned Count = 0;
27244 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
27246 llvm::is_contained(Modifiers, MotionModifiers[I])) {
27247 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
27251 "Modifiers exceed the allowed number of motion modifiers");
27252 Modifiers[Count] = MotionModifiers[I];
27253 ModifiersLoc[Count] = MotionModifiersLoc[I];
27257 MappableVarListInfo MVLI(VarList);
27259 MapperIdScopeSpec, MapperId, UnresolvedMappers);
27260 if (MVLI.ProcessedVarList.empty())
27263 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
27264 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
27267 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27268 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
27285 unsigned Count = 0;
27286 for (
unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
27288 llvm::is_contained(Modifiers, MotionModifiers[I])) {
27289 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
27293 "Modifiers exceed the allowed number of motion modifiers");
27294 Modifiers[Count] = MotionModifiers[I];
27295 ModifiersLoc[Count] = MotionModifiersLoc[I];
27299 MappableVarListInfo MVLI(VarList);
27301 MapperIdScopeSpec, MapperId, UnresolvedMappers);
27302 if (MVLI.ProcessedVarList.empty())
27305 if (
auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
27306 if (
auto *VD = dyn_cast<VarDecl>(DRE->
getDecl()))
27309 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27310 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
27319 MappableVarListInfo MVLI(VarList);
27323 for (
Expr *RefExpr : VarList) {
27324 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
27327 Expr *SimpleRefExpr = RefExpr;
27331 MVLI.ProcessedVarList.push_back(RefExpr);
27332 PrivateCopies.push_back(
nullptr);
27333 Inits.push_back(
nullptr);
27340 Type =
Type.getNonReferenceType().getUnqualifiedType();
27342 auto *VD = dyn_cast<VarDecl>(D);
27346 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
27347 << 0 << RefExpr->getSourceRange();
27356 if (VDPrivate->isInvalidDecl())
27359 SemaRef.CurContext->addDecl(VDPrivate);
27361 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
27368 SemaRef.AddInitializerToDecl(
27369 VDPrivate,
SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
27377 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
27378 PrivateCopies.push_back(VDPrivateRefExpr);
27379 Inits.push_back(VDInitRefExpr);
27384 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
27388 MVLI.VarBaseDeclarations.push_back(D);
27389 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
27390 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
27394 if (MVLI.ProcessedVarList.empty())
27399 MVLI.VarBaseDeclarations, MVLI.VarComponents, FallbackModifier,
27400 FallbackModifierLoc);
27406 MappableVarListInfo MVLI(VarList);
27408 for (
Expr *RefExpr : VarList) {
27409 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
27412 Expr *SimpleRefExpr = RefExpr;
27418 MVLI.ProcessedVarList.push_back(RefExpr);
27423 auto *VD = dyn_cast<VarDecl>(D);
27430 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
27435 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
27441 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
27448 assert(!CurComponents.empty() &&
27449 "use_device_addr clause expression with no components!");
27466 CurComponents,
DSAStack->getCurrentDirective());
27467 const Expr *AttachPtrExpr = AttachPtrResult.first;
27469 if (AttachPtrExpr) {
27471 bool IsValidBase =
false;
27474 IsValidBase =
true;
27475 else if (
const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
27477 IsValidBase =
true;
27479 if (!IsValidBase) {
27481 diag::err_omp_expected_base_pointer_var_name_member_expr)
27482 << (
SemaRef.getCurrentThisType().isNull() ? 0 : 1)
27489 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
27491 "Unexpected null decl for use_device_addr clause.");
27493 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
27494 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
27495 MVLI.VarComponents.back().append(CurComponents.begin(),
27496 CurComponents.end());
27499 if (MVLI.ProcessedVarList.empty())
27503 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27504 MVLI.VarComponents);
27510 MappableVarListInfo MVLI(VarList);
27511 for (
Expr *RefExpr : VarList) {
27512 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
27515 Expr *SimpleRefExpr = RefExpr;
27519 MVLI.ProcessedVarList.push_back(RefExpr);
27529 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
27530 << 0 << RefExpr->getSourceRange();
27536 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
27539 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
27542 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
27548 const Expr *ConflictExpr;
27549 if (
DSAStack->checkMappableExprComponentListsForDecl(
27554 ConflictExpr = R.front().getAssociatedExpression();
27557 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
27566 SimpleRefExpr, D,
false);
27567 DSAStack->addMappableExpressionComponents(
27568 D, MC, OMPC_is_device_ptr);
27571 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
27578 "Unexpected device pointer expression!");
27579 MVLI.VarBaseDeclarations.push_back(
27581 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
27582 MVLI.VarComponents.back().push_back(MC);
27585 if (MVLI.ProcessedVarList.empty())
27589 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27590 MVLI.VarComponents);
27596 MappableVarListInfo MVLI(VarList);
27597 for (
Expr *RefExpr : VarList) {
27598 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
27601 Expr *SimpleRefExpr = RefExpr;
27606 MVLI.ProcessedVarList.push_back(RefExpr);
27614 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D,
false);
27617 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
27620 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective(),
27626 const Expr *ConflictExpr;
27627 if (
DSAStack->checkMappableExprComponentListsForDecl(
27632 ConflictExpr = R.front().getAssociatedExpression();
27635 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
27643 Expr *Component = SimpleRefExpr;
27644 auto *VD = dyn_cast<VarDecl>(D);
27648 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
27650 Component, D,
false);
27651 DSAStack->addMappableExpressionComponents(
27652 D, MC, OMPC_has_device_addr);
27655 if (!VD && !
SemaRef.CurContext->isDependentContext()) {
27658 assert(Ref &&
"has_device_addr capture failed");
27659 MVLI.ProcessedVarList.push_back(Ref);
27661 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
27668 "Unexpected device pointer expression!");
27669 MVLI.VarBaseDeclarations.push_back(
27671 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
27672 MVLI.VarComponents.back().push_back(MC);
27675 if (MVLI.ProcessedVarList.empty())
27679 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27680 MVLI.VarComponents);
27694 bool AllocDependent =
27698 if (!AllocDependent) {
27707 AllocatorRes =
SemaRef.PerformImplicitConversion(
27708 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
27713 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
27722 !
DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
27723 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
27730 if (!AlignmentDependent) {
27733 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
27738 for (
Expr *RefExpr : VarList) {
27739 assert(RefExpr &&
"NULL expr in OpenMP allocate clause.");
27742 Expr *SimpleRefExpr = RefExpr;
27746 Vars.push_back(RefExpr);
27752 auto *VD = dyn_cast<VarDecl>(D);
27754 if (!VD && !
SemaRef.CurContext->isDependentContext())
27756 Vars.push_back((VD ||
SemaRef.CurContext->isDependentContext())
27757 ? RefExpr->IgnoreParens()
27765 DSAStack->addInnerAllocatorExpr(Allocator);
27768 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
27769 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
27770 SecondAllocateModifierLoc, EndLoc, Vars);
27778 for (
Expr *RefExpr : VarList) {
27779 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
27782 Expr *SimpleRefExpr = RefExpr;
27786 Vars.push_back(RefExpr);
27793 if (
const Expr *PrevRef =
27794 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
27795 Diag(ELoc, diag::err_omp_used_in_clause_twice)
27797 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
27802 Vars.push_back(RefExpr);
27819 SemaRef.setFunctionHasBranchProtectedScope();
27830 for (
Expr *RefExpr : VarList) {
27831 assert(RefExpr &&
"NULL expr in OpenMP inclusive clause.");
27834 Expr *SimpleRefExpr = RefExpr;
27839 Vars.push_back(RefExpr);
27844 const DSAStackTy::DSAVarData DVar =
27850 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
27851 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
27852 << RefExpr->getSourceRange();
27854 if (
DSAStack->getParentDirective() != OMPD_unknown)
27855 DSAStack->markDeclAsUsedInScanDirective(D);
27856 Vars.push_back(RefExpr);
27871 for (
Expr *RefExpr : VarList) {
27872 assert(RefExpr &&
"NULL expr in OpenMP exclusive clause.");
27875 Expr *SimpleRefExpr = RefExpr;
27880 Vars.push_back(RefExpr);
27886 DSAStackTy::DSAVarData DVar;
27887 if (ParentDirective != OMPD_unknown)
27888 DVar =
DSAStack->getTopDSA(D,
true);
27893 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
27894 DVar.Modifier != OMPC_REDUCTION_inscan) {
27895 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
27896 << RefExpr->getSourceRange();
27898 DSAStack->markDeclAsUsedInScanDirective(D);
27900 Vars.push_back(RefExpr);
27912 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
27913 if (!OMPAlloctraitT.
isNull())
27918 S.
Diag(Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
27921 Stack->setOMPAlloctraitT(PT.
get());
27941 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
27942 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
27943 StringRef Allocator =
27944 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
27946 PredefinedAllocators.insert(
SemaRef.LookupSingleName(
27952 Expr *AllocatorExpr =
nullptr;
27960 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
27961 bool IsPredefinedAllocator =
false;
27963 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
27965 IsPredefinedAllocator =
27967 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
27971 bool IsTypeCompatible = IsPredefinedAllocator;
27972 IsTypeCompatible = IsTypeCompatible ||
27973 Context.hasSameUnqualifiedType(AllocatorExprType,
27974 OMPAllocatorHandleT);
27976 IsTypeCompatible ||
27977 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
27978 bool IsNonConstantLValue =
27980 if (!DRE || !IsTypeCompatible ||
27981 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
27983 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
27992 diag::err_omp_predefined_allocator_with_traits)
28005 diag::err_omp_nonpredefined_allocator_without_traits);
28011 AllocatorExpr =
SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
28014 IsPredefinedAllocator
28015 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
28016 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
28018 Expr *AllocatorTraitsExpr =
nullptr;
28032 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
28033 TraitTy = ConstArrayTy->getElementType();
28035 !(Context.hasSameUnqualifiedType(TraitTy,
28037 Context.typesAreCompatible(TraitTy,
DSAStack->getOMPAlloctraitT(),
28040 diag::err_omp_expected_array_alloctraits)
28041 << AllocatorTraitsExpr->
getType();
28046 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
28049 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
28066 for (
Expr *RefExpr : Locators) {
28067 assert(RefExpr &&
"NULL expr in OpenMP affinity clause.");
28070 Vars.push_back(RefExpr);
28078 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
28079 << 1 << 0 << RefExpr->getSourceRange();
28090 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
28091 << 1 << 0 << RefExpr->getSourceRange();
28098 ColonLoc, EndLoc, Modifier, Vars);
28107 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
28122 Expr *ValExpr = Size;
28123 Stmt *HelperValStmt =
nullptr;
28134 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().getOpenMPVersion());
28135 if (CaptureRegion != OMPD_unknown &&
28136 !
SemaRef.CurContext->isDependentContext()) {
28137 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
28138 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
28139 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
28144 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
28159 diag::err_omp_unexpected_clause_value)
28160 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
28164 Expr *ValExpr = Size;
28165 Stmt *HelperValStmt =
nullptr;
28176 DKind, OMPC_dyn_groupprivate,
getLangOpts().getOpenMPVersion());
28177 if (CaptureRegion != OMPD_unknown &&
28178 !
SemaRef.CurContext->isDependentContext()) {
28179 ValExpr =
SemaRef.MakeFullExpr(ValExpr).get();
28180 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
28181 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
28186 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
28195 if (
DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
28196 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
28197 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
28198 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
28199 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
28205 DSAStackTy::OperatorOffsetTy OpsOffs;
28206 llvm::APSInt TotalDepCount(32);
28209 DepType == OMPC_DOACROSS_source ||
28210 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
28211 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
28213 Vars = VarOffset.Vars;
28214 OpsOffs = VarOffset.OpsOffs;
28215 TotalDepCount = VarOffset.TotalDepCount;
28217 EndLoc, DepType, DepLoc, ColonLoc, Vars,
28218 TotalDepCount.getZExtValue());
28219 if (
DSAStack->isParentOrderedRegion())
28220 DSAStack->addDoacrossDependClause(
C, OpsOffs);
28243 return new (
getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
28251 return OMPAbsentClause::Create(
getASTContext(), DKVec, Loc, LLoc, RLoc);
28252 case OMPC_contains:
28253 return OMPContainsClause::Create(
getASTContext(), DKVec, Loc, LLoc, RLoc);
28255 llvm_unreachable(
"Unexpected OpenMP clause");
28263 case OMPC_no_openmp:
28265 case OMPC_no_openmp_routines:
28266 return new (
getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
28267 case OMPC_no_parallelism:
28268 return new (
getASTContext()) OMPNoParallelismClause(Loc, RLoc);
28269 case OMPC_no_openmp_constructs:
28270 return new (
getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
28272 llvm_unreachable(
"Unexpected OpenMP clause");
28281 if (
Base->hasPlaceholderType() &&
28282 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
28295 LowerBound =
Result.get();
28297 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
28317 if (
Base->isTypeDependent() ||
28320 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
28323 Base, LowerBound, Length, Stride, Context.DependentTy,
VK_LValue,
28324 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
28336 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
28337 <<
Base->getSourceRange());
28343 if (Res.isInvalid())
28345 diag::err_omp_typecheck_section_not_integer)
28347 LowerBound = Res.get();
28357 if (Res.isInvalid())
28359 diag::err_omp_typecheck_section_not_integer)
28360 << 1 << Length->getSourceRange());
28361 Length = Res.get();
28363 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
28364 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
28365 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
28366 << 1 << Length->getSourceRange();
28373 diag::err_omp_typecheck_section_not_integer)
28375 Stride = Res.
get();
28388 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
28389 << ResultTy <<
Base->getSourceRange();
28393 if (
SemaRef.RequireCompleteType(
Base->getExprLoc(), ResultTy,
28394 diag::err_omp_section_incomplete_type,
Base))
28402 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
28403 if (LowerBoundValue.isNegative()) {
28405 diag::err_omp_section_not_subset_of_array)
28414 if (Length->EvaluateAsInt(
Result, Context)) {
28417 llvm::APSInt LengthValue =
Result.Val.getInt();
28418 if (LengthValue.isNegative()) {
28419 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
28420 <<
toString(LengthValue, 10,
true)
28421 << Length->getSourceRange();
28425 }
else if (
SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.
isValid() &&
28431 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
28441 llvm::APSInt StrideValue =
Result.Val.getInt();
28442 if (!StrideValue.isStrictlyPositive()) {
28443 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
28444 <<
toString(StrideValue, 10,
true)
28451 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
28458 Base, LowerBound, Length, Stride, Context.ArraySectionTy,
VK_LValue,
28459 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
28466 if (
Base->hasPlaceholderType()) {
28480 LParenLoc, RParenLoc, Dims, Brackets);
28482 (!
Base->isTypeDependent() &&
28485 diag::err_omp_non_pointer_type_array_shaping_base)
28486 <<
Base->getSourceRange());
28489 bool ErrorFound =
false;
28491 if (
Dim->hasPlaceholderType()) {
28493 if (
Result.isInvalid()) {
28498 if (
Result.isInvalid()) {
28504 if (!
Dim->isTypeDependent()) {
28507 if (
Result.isInvalid()) {
28509 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
28510 <<
Dim->getSourceRange();
28515 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
28520 if (!
Value.isStrictlyPositive()) {
28521 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
28523 <<
Dim->getSourceRange();
28529 NewDims.push_back(
Dim);
28534 LParenLoc, RParenLoc, NewDims, Brackets);
28544 bool IsCorrect =
true;
28549 if (!D.Type.getAsOpaquePtr()) {
28553 DeclTy = Context.IntTy;
28554 StartLoc = D.DeclIdentLoc;
28563 if (!IsDeclTyDependent) {
28567 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
28575 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
28583 assert(D.DeclIdent &&
"Identifier expected.");
28588 D.DeclIdent, DeclTy, TInfo,
SC_None);
28606 SemaRef.PushOnScopeChains(VD, S);
28609 SemaRef.CurContext->addDecl(VD);
28615 Expr *Begin = D.Range.Begin;
28619 Begin = BeginRes.
get();
28621 Expr *End = D.Range.End;
28625 End = EndRes.
get();
28627 Expr *Step = D.Range.Step;
28630 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
28635 std::optional<llvm::APSInt>
Result =
28641 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
28647 if (!Begin || !End || !IsCorrect) {
28663 if (
Decl *ID = D.IteratorDecl)
28664 ID->setInvalidDecl();
28669 if (!
SemaRef.CurContext->isDependentContext()) {
28676 D.Range.End, D.Range.Begin);
28682 if (D.Range.Step) {
28685 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.
get(),
28692 Res =
SemaRef.CreateBuiltinBinOp(
28693 D.AssignmentLoc, BO_Sub, Res.
get(),
28694 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
28700 Res =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.
get(),
28706 St1 =
SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
28710 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
28716 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.
get(),
28723 Res1 =
SemaRef.CreateBuiltinBinOp(
28724 D.AssignmentLoc, BO_Sub, Res1.
get(),
28725 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
28731 Res1 =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.
get(),
28739 D.AssignmentLoc, BO_GT, D.Range.Step,
28740 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
28745 Res =
SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
28752 Res =
SemaRef.ActOnFinishFullExpr(Res.
get(),
false);
28764 CounterVD->setImplicit();
28771 if (D.Range.Step) {
28772 UpdateRes =
SemaRef.CreateBuiltinBinOp(
28773 D.AssignmentLoc, BO_Mul,
28774 SemaRef.DefaultLvalueConversion(RefRes.
get()).get(), St.
get());
28776 UpdateRes =
SemaRef.DefaultLvalueConversion(RefRes.
get());
28782 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
28783 D.Range.Begin, UpdateRes.
get());
28792 UpdateRes =
SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
28793 VDRes.
get(), UpdateRes.
get());
28799 SemaRef.ActOnFinishFullExpr(UpdateRes.
get(),
true);
28805 D.AssignmentLoc, UO_PreInc, RefRes.
get());
28806 if (!CounterUpdateRes.
isUsable()) {
28810 CounterUpdateRes =
SemaRef.ActOnFinishFullExpr(CounterUpdateRes.
get(),
28812 if (!CounterUpdateRes.
isUsable()) {
28823 Helpers.assign(ID.size(), {});
28828 if (
Decl *ID = D.IteratorDecl)
28829 ID->setInvalidDecl();
28834 LLoc, RLoc, ID, Helpers);
28839 StringRef AssumptionStr) {
28840 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
28843 unsigned BestEditDistance = 3;
28844 StringRef Suggestion;
28845 for (
const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
28846 unsigned EditDistance =
28847 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
28848 if (EditDistance < BestEditDistance) {
28849 Suggestion = KnownAssumptionIt.getKey();
28850 BestEditDistance = EditDistance;
28854 if (!Suggestion.empty())
28855 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
28856 << AssumptionStr << Suggestion;
28858 S.
Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
28866 if (!
SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
Result
Implement __builtin_bit_cast and related operations.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::TargetList TargetList
This file defines OpenMP AST classes for clauses.
bool resolveOMPAdjustArgsItem(const OMPAdjustArgsItem &Item, const FunctionDecl *FD, unsigned NumArgs, const ASTContext &Ctx, SmallVectorImpl< unsigned > &Positions)
Resolve one 'adjust_args' parameter-list item to the 1-based argument positions it identifies (OpenMP...
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static bool checkOMPAdjustArgsBound(SemaOpenMP &S, const OMPAdjustArgsItem::Bound &Bound)
Check one bound of a parameter range 'lb:ub' (OpenMP 6.0 [5.2.1]).
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static bool hasConstQualifiedMappingType(QualType T)
static void updatePreInits(OMPLoopTransformationDirective *Transform, SmallVectorImpl< Stmt * > &PreInits)
Updates OriginalInits by checking Transform against loop transformation directives and appending thei...
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static Stmt * buildLoopFinalization(ASTContext &Context, ArrayRef< OMPLoopBasedDirective::HelperExprs > LoopHelpers, ArrayRef< Stmt * > LoopStmts, ArrayRef< Stmt * > NestedFinals={})
Build loop variable finalization statement from HelperExprs.Finals.
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 bool isDeadAfterLoop(const Expr *Counter, const Stmt *LoopStmt)
Whether Counter is dead after LoopStmt: compiler generated (e.g.
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 bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static OMPClause * createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg, Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls, llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopInductionVars)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static 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 void appendStmtsBeforeNestedLoop(Stmt *LoopStmt, SmallVectorImpl< Stmt * > &BodyParts)
A non-innermost affected loop generated by a nested loop transformation (e.g.
static bool checkDecompositionCaptureConflict(Sema &SemaRef, OpenMPDirectiveKind DKind, llvm::SmallDenseMap< const DecompositionDecl *, std::pair< bool, SourceLocation >, 4 > &SeenDecompositions, const ValueDecl *D, SourceLocation ELoc, OpenMPClauseKind ClauseKind)
Check if bindings from the same structured binding have conflicting capture kinds (by-ref vs by-copy)...
static bool validateMultidimClauses(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, bool MayHaveBareClause=false)
Check the number of expressions specified in clauses that can contain multidimensional values,...
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 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 OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, llvm::omp::Version OMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
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 ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper, SourceLocation ItemLoc)
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static bool validateMultidimClauseExprs(SemaBase &SemaRef, OpenMPClauseKind ClauseKind, SourceLocation ClauseBeginLoc, ArrayRef< const Expr * > ClauseVarList, const Expr *DimsModifierExpr, const OMPXBareClause *BareClause=nullptr)
Check the number of expressions specified in a multidimensional clause and return whether an error wa...
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, bool AllowAssumedSizeArray=false, StringRef DiagType="")
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkClausesForDecompositionConflicts(Sema &SemaRef, OpenMPDirectiveKind DKind, ArrayRef< OMPClause * > Clauses, Stmt *Body=nullptr)
Helper to check all clauses in a directive for structured binding capture conflicts.
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static bool hasNoMutableFields(const CXXRecordDecl *RD)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static bool checkOMPAdjustArgsRange(SemaOpenMP &S, const OMPAdjustArgsItem &Range)
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 Expr * buildInitListValue(Sema &SemaRef, Expr *E)
static Stmt * guardByLoopPreConds(ASTContext &Context, ArrayRef< OMPLoopBasedDirective::HelperExprs > Loops, Stmt *S)
Wrap S so it runs only if every loop in Loops has iterations.
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts, bool RelaxNestForPeeledTransformation=false)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static OMPAdjustArgsVal checkOMPAdjustArgsValue(SemaOpenMP &S, Expr *E, bool StrictlyPositive, llvm::APSInt &Result)
Check one 'adjust_args' integer expression for the constant property plus either the positive or the ...
static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static SourceLocation getOMPAdjustArgsItemLoc(const OMPAdjustArgsItem &Item, SourceLocation FallbackLoc)
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static bool checkPreferTypeArgs(SemaOpenMP &S, const OMPInteropInfo &Info)
Validate prefer_type fr() and attr() arguments in an OMPInteropInfo.
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void guardNestedLoopInit(ASTContext &Context, ArrayRef< OMPLoopBasedDirective::HelperExprs > LoopHelpers, unsigned I, SmallVectorImpl< Stmt * > &OriginalInit)
Run loop I's inits only if all enclosing loops have iterations.
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget, bool HasConstQualifier)
static bool checkOriginalVarMappedButOnlyBindingsUsed(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, Stmt *Body)
Check if original variable is explicitly mapped but only bindings are used.
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propagated from the selected loop.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static QualType getIntTypeForBitwidthOrBitInt(ASTContext &C, unsigned Bits, bool Signed)
Like ASTContext::getIntTypeForBitwidth, but falls back to a _BitInt type when no standard integer typ...
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
static QualType getPointeeType(const MemRegion *R)
VerifyDiagnosticConsumer::Directive Directive
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override
bool VisitVarDecl(VarDecl *D) override
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F) override
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override
NestedLoopCounterVisitor()=default
bool VisitForStmt(ForStmt *FS) override
bool TraverseStmt(Stmt *S) override
bool TraverseDecl(Decl *D) override
unsigned getNestedLoopCount() const
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
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 OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Class that represents a component of a mappable expression. E.g. for an expression S....
ValueDecl * getAssociatedDeclaration() const
SmallVector< MappableComponent, 8 > MappableExprComponentList
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
DeclarationNameInfo getDirectiveName() const
Return name of the 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.
This represents implicit clause 'depobj' for the 'pragma omp depobj' directive. This clause does not ...
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' dir...
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'filter' clause in the 'pragma omp ...' directive.
static OMPFlattenDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp flatten'.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static 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, Expr *IteratorExpr, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
static OMPFuseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumGeneratedTopLevelLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for pragma omp fuse'.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the 'pragma omp ...' directive.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static 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 'nocontext' clause in the 'pragma omp ...' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, OpenMPNumTeamsClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'order' clause in the 'pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
static OMPOrderedBlockAssocDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPOrderedStandaloneDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
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.
This represents 'priority' clause in the 'pragma omp ...' directive.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, unsigned NumLoops, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp reverse'.
This represents 'simd' clause in the 'pragma omp ...' directive.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static 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.
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.
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPSplitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp split'.
static OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp stripe'.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static 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, OpenMPThreadLimitClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'threads' clause in the 'pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp tile'.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedTopLevelLoops, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp unroll'.
This represents the 'use' clause in 'pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Creates clause with a list of variables Vars.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
void Deallocate(void *Ptr) const
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return a non-unique reference to the type for a variable array of the specified element type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Expr * getBase()
Get base of the array section.
Expr * getLength()
Get length of array section.
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Expr * getLowerBound()
Get lower bound of array section.
SourceLocation getColonLocFirst() const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Attr - This represents one attribute.
Represents an attribute applied to a statement.
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
SourceLocation getBeginLoc() const
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isRelationalOp(Opcode Opc)
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
static Opcode getOpForCompoundAssignment(Opcode Opc)
SourceLocation getOperatorLoc() const
SourceLocation getExprLoc() const
static Opcode reverseComparisonOp(Opcode Opc)
static bool isAdditiveOp(Opcode Opc)
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
BinaryOperatorKind Opcode
A binding in a decomposition declaration.
VarDecl * getHoldingVar() const
Get the variable (if any) that holds the value of evaluating the binding.
Expr * getBinding() const
Get the expression to which this declaration is bound.
DecompositionDecl * getDecomposedDecl() const
Get the decomposition declaration that this binding represents a decomposition of.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Represents a C++ constructor within a class.
Represents a C++ conversion function within a class.
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Represents a C++ struct/union/class.
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
bool hasDefinition() const
Represents a C++ nested-name-specifier or a global scope specifier.
bool isValid() const
A scope specifier is present, and it refers to a real scope.
SourceLocation getBeginLoc() const
bool isSet() const
Deprecated.
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
bool isInvalid() const
An error occurred during parsing of the scope specifier.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
SourceLocation getBeginLoc() const
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
A wrapper class around a pointer that always points to its canonical declaration.
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getNumParams() const
void setNothrow(bool Nothrow=true)
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
SourceRange getSourceRange() const LLVM_READONLY
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
SourceLocation getBeginLoc() const LLVM_READONLY
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Declaration of a class template.
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
SourceLocation getBeginLoc() const
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
ConditionalOperator - The ?
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
bool isFileContext() const
DeclContextLookupResult lookup_result
ASTContext & getParentASTContext() const
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
bool isTranslationUnit() const
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context semantically encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
bool isSingleDecl() const
A reference to a declared variable, function, enum, etc.
NamedDecl * getFoundDecl()
Get the NamedDecl through which this reference occurred.
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
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)
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const
SourceLocation getLocation() const
ConstexprSpecKind getConstexprSpecifier() const
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
SourceLocation getEndLoc() const
const DeclGroupRef getDeclGroup() const
const Decl * getSingleDecl() const
SourceLocation getBeginLoc() const LLVM_READONLY
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
bool isReferenced() const
Whether any declaration of this entity was referenced.
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
bool isInvalidDecl() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
void setAccess(AccessSpecifier AS)
SourceLocation getLocation() const
void setImplicit(bool I=true)
void setReferenced(bool R=true)
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
DeclContext * getDeclContext()
AccessSpecifier getAccess() const
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.
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
SourceLocation getIdentifierLoc() const
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
SourceLocation getBeginLoc() const LLVM_READONLY
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
bool isInvalidType() const
const IdentifierInfo * getIdentifier() const
A decomposition declaration.
OriginalVarResult getOriginalVar() const
If this decomposition was initialized from a variable (e.g., auto [a,b] = p), returns the variable.
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
RAII object that enters a new expression evaluation context.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isIntegerConstantExpr(const ASTContext &Ctx) const
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
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 HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
bool isMutable() const
Determines whether this field is mutable (C++ only).
bool isBitField() const
Determines whether this field is a bitfield.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
ArrayRef< ParmVarDecl * > parameters() const
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Represents a prototype with parameter type info, e.g.
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, SourceLocation RPL, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)
Create an IfStmt.
SourceLocation getBeginLoc() const
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeTemporary(QualType Type)
Create the initialization entity for a temporary.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
llvm::omp::Version getOpenMPVersion() const
Return the OpenMP version.
A class for iterating through a result set and possibly filtering out results.
Represents the results of name lookup.
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
DeclClass * getAsSingle() const
bool empty() const
Return true if no decls were found.
Filter makeFilter()
Create a filter for this result set.
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
static MemberExpr * Create(const ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR)
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
SourceLocation getExprLoc() const LLVM_READONLY
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
void setDeclName(DeclarationName N)
Set the name of this declaration.
A C++ nested-name-specifier augmented with source location information.
Describes the source-level contents of one OpenMP 'adjust_args' clause.
static OMPAdjustArgsDescriptor * Create(const ASTContext &C, OpenMPAdjustArgsOpKind AdjustOp, OpenMPNeedDevicePtrModifier NeedDevicePtrModifier, ArrayRef< OMPAdjustArgsItem > Items)
This represents the 'align' clause in the 'pragma omp allocate' directive.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the 'pragma omp ...' directive.
Expr * getBase()
Fetches base expression of array shaping expression.
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Pseudo declaration for capturing expressions.
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'schedule',...
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
SourceLocation getEndLoc() const
Returns the ending location of the clause.
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
This represents 'collapse' clause in the 'pragma omp ...' directive.
static OMPCountsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Counts, std::optional< unsigned > FillIdx, SourceLocation FillLoc)
Build a 'counts' AST node.
This represents 'pragma omp declare mapper ...' directive.
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents 'pragma omp declare reduction ...' directive.
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the 'pragma omp ...' directive.
This represents the 'depth' clause on the 'pragma omp flatten' (and 'pragma omp fuse') loop-transform...
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'pragma omp groupprivate ...' directive.
static OMPGroupPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'if' clause in the 'pragma omp ...' directive.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
This class represents the 'looprange' clause in the 'pragma omp fuse' directive.
static OMPNumThreadsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, OpenMPNumThreadsClauseModifier PrescriptivenessModifier, OpenMPNumThreadsClauseModifier DimsModifier, SourceLocation PrescriptivenessModifierLoc, SourceLocation DimsModifierLoc, Expr *DimsModifierExpr, Stmt *PreInit)
Creates clause with a list of variables/expressions.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This class represents the 'permutation' clause in the 'pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
This represents 'pragma omp threadprivate ...' directive.
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threadset' clause in the 'pragma omp task ...' directive.
void * getAsOpaquePtr() const
static OpaquePtr make(DeclGroupRef P)
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Represents a parameter to a function.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
ParsedAttr - Represents a syntactic attribute.
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
A (possibly-)qualified type.
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool hasQualifiers() const
Determine whether this type has any qualifiers.
QualType withRestrict() const
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
QualType withConst() const
void addConst()
Add the const type qualifier to this QualType.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
bool isConstant(const ASTContext &Ctx) const
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool isMoreQualifiedThan(QualType Other, const ASTContext &Ctx) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
const Type * getTypePtrOrNull() const
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
const Scope * getParent() const
getParent - Return the scope that this is nested in.
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
A generic diagnostic builder for errors which may or may not be deferred.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of 'pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
OMPClause * ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'threadset' clause.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPSplitDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp split' after parsing of its associated statement.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
StmtResult ActOnOpenMPFlattenDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp flatten' after parsing of its clauses and the associated statement.
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.
ExprResult ActOnOpenMPDimsModifier(OpenMPClauseKind Kind, int Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, ArrayRef< Expr * > VarList, SourceLocation VarListEndLoc)
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a 'pragma omp end declare target' was enc...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
ArrayRef< const OMPRequiresDecl * > getRequiresDecls() const
The 'requires' directives seen so far in this translation unit.
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of 'pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPCountsClause(ArrayRef< Expr * > CountExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, std::optional< unsigned > FillIdx, SourceLocation FillLoc, unsigned FillCount)
Called on well-formed 'counts' clause after parsing its arguments.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
OMPClause * ActOnOpenMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the 'pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed 'pragma omp requires'.
OMPGroupPrivateDecl * CheckOMPGroupPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPGroupPrivateDecl and checks its correctness.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPLoopRangeClause(Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc)
Called on well-form 'looprange' clause after parsing its arguments.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
StmtResult ActOnOpenMPFuseDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp fuse' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the 'pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed 'pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed 'pragma omp allocate'.
OMPClause * ActOnOpenMPUpdateDependObjectsClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update_depend_objects' clause.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
OMPAdjustArgsDescriptor * ActOnOpenMPAdjustArgsClause(OpenMPAdjustArgsOpKind AdjustOp, OpenMPNeedDevicePtrModifier NeedDevicePtrModifier, ArrayRef< OMPAdjustArgsItem > Items, SourceLocation Loc)
Called on well-formed 'adjust_args' clause of a '#pragma omp declare variant' directive.
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)
void addRequiresDecl(OMPRequiresDecl *D)
Registers a 'requires' directive deserialized from an AST file.
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of 'pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
DeclGroupPtrTy ActOnOpenMPGroupPrivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp groupprivate'.
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'task_reduction' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc, Expr *Condition)
Called on well-formed 'nowait' clause.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
StmtResult ActOnOpenMPStripeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. 'pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
OMPClause * ActOnOpenMPNumThreadsClause(ArrayRef< Expr * > VarList, OpenMPNumThreadsClauseModifier SimpleModifier, SourceLocation SimpleModifierLoc, OpenMPNumThreadsClauseModifier ComplexModifier, Expr *ComplexModifierExpr, SourceLocation ComplexModifierLoc, 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 statem...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
void setOpenMPDeviceNumID(StringRef ID)
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, OpenMPThreadLimitClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
int getOpenMPDeviceNum() const
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPTransparentClause(Expr *Transparent, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'transparent' clause.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, OpenMPNumTeamsClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, OpenMPNumTeamsClauseModifier ModifierExtra, Expr *ModifierExtraExpr, SourceLocation ModifierExtraLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
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.
StmtResult ActOnOpenMPMetaDirective(SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPTraitInfo * > TraitInfos, ArrayRef< Stmt * > Variants)
Called for metadirectives with user conditions that require runtime selection.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< OMPAdjustArgsDescriptor * > AdjustArgs, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, Expr *IteratorModifier, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' clause.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPDynGroupprivateClause(OpenMPDynGroupprivateClauseModifier M1, OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation EndLoc)
Called on a well-formed 'dyn_groupprivate' clause.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, Expr *IteratorModifier, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'to' clause.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'reduction' clause.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind M, SourceLocation MLoc, OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp tile' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed 'pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. 'pragma omp end declare target'.
OMPClause * ActOnOpenMPDepthClause(Expr *DepthExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depth' clause.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called for 'pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Abstract base class used for diagnosing integer constant expression violations.
Sema - This implements semantic analysis and AST building for C.
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false) const
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
@ LookupAnyName
Look up any declaration with any name.
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
FPOptionsOverride CurFPFeatureOverrides()
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
ASTContext & getASTContext() const
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt)
Try to capture the given variable.
void PopExpressionEvaluationContext()
llvm::SmallSetVector< CXXRecordDecl *, 16 > AssociatedClassSet
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef< Expr * > Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses)
Find the associated classes and namespaces for argument-dependent lookup for a call with the given se...
const LangOptions & getLangOpts() const
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)
Checks access for a hierarchy conversion.
ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type, SourceLocation LParenLoc, MultiExprArg Exprs, SourceLocation RParenLoc, bool ListInitialization)
const LangOptions & LangOpts
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
DeclContext * getCurLexicalContext() const
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
ExprResult DefaultLvalueConversion(Expr *E)
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, CXXRecordDecl *Base, CXXBasePaths &Paths)
Determine whether the type Derived is a C++ class that is derived from the type Base.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
void setFunctionHasBranchProtectedScope()
std::pair< StringRef, QualType > CapturedParamNameType
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=AllowFoldKind::No)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
FullExprArg MakeFullExpr(Expr *Arg)
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
SourceLocation getBeginLoc() const LLVM_READONLY
void Visit(PTR(Stmt) S, ParamTys... P)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
SourceLocation getEndLoc() const LLVM_READONLY
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool isTLSSupported() const
Whether the target supports thread-local storage.
Represents a declaration of a type.
SourceLocation getBeginLoc() const
Get the begin source location.
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
QualType getType() const
Return the type wrapped by this type source info.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantArrayType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
bool isArithmeticType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isEnumeralType() const
bool isScalarType() const
bool isVariableArrayType() const
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
bool isAnyComplexType() const
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isFunctionProtoType() const
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
bool isFunctionType() const
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
bool isStructureOrClassType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
bool isFunctionNoProtoType() const
Represents the declaration of a typedef-name via the 'typedef' type specifier.
Base class for declarations which introduce a typedef-name.
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
Expr * getSubExpr() const
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
void setType(QualType newType)
VarDecl * getPotentiallyDecomposedVarDecl()
const Expr * getExprStmt() const
Represents a variable declaration or definition.
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
void setInitStyle(InitializationStyle Style)
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
@ CallInit
Call-style initialization (C++98)
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
StorageClass getStorageClass() const
Returns the storage class as written in the source.
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Retains information about a captured region.
unsigned short OpenMPLevel
unsigned short OpenMPCaptureLevel
Retains information about a function, method, or block that is currently being parsed.
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Defines the clang::TargetInfo interface.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
Top level wrappers for InstallAPI frontend operations.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
@ OMPC_DEFAULT_VC_unknown
Stmt Stmt llvm::function_ref< void(OMPLoopTransformationDirective *)> bool RelaxNestForPeeledTransformation
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
OpenMPNeedDevicePtrModifier
OpenMP 6.1 need_device modifier.
@ OMPC_NEED_DEVICE_PTR_unknown
OpenMPAdjustArgsOpKind
OpenMP adjust-op kinds for 'adjust_args' clause.
@ Comparison
A comparison.
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
@ OK_Ordinary
An ordinary object is located at an address in memory.
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Expr * AssertSuccess(ExprResult R)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
@ LCK_This
Capturing the *this object by reference.
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Seq
'seq' clause, allowed on 'loop' and 'routine' directives.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
ActionResult< Decl * > DeclResult
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
OpenMPNumTeamsClauseModifier
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
@ Dependent
Parse the block as a dependent block, which may be used in some template instantiations but not other...
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
OpenMPDynGroupprivateClauseFallbackModifier
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
MutableArrayRef< Expr * > MultiExprArg
@ SD_Static
Static storage duration.
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
ActionResult< ParsedType > TypeResult
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
const FunctionProtoType * T
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
bool isOpenMPCanonicalLoopNestTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPNumTasksClauseModifier
OpenMPUseDevicePtrFallbackModifier
OpenMP 6.1 use_device_ptr fallback modifier.
@ OMPC_USE_DEVICE_PTR_FALLBACK_unknown
bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
OpenMPDynGroupprivateClauseModifier
@ OMPC_DYN_GROUPPRIVATE_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
OpenMPThreadLimitClauseModifier
@ OMPC_THREADLIMIT_unknown
bool isOpenMPSimdizableDirective(OpenMPDirectiveKind DKind, OpenMPBindClauseKind BindKind, const LangOptions &LangOpts)
Checks if the specified directive is a simdizable directive, i.e.
SmallVector< CXXBaseSpecifier *, 4 > CXXCastPath
A simple array of base specifiers.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ None
No keyword precedes the qualified type name.
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
ActionResult< Expr * > ExprResult
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
ActionResult< Stmt * > StmtResult
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
int const char * function
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Clang specific specialization of the OMPContext to lookup target features.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
Extra information about a function prototype.
One bound of a parameter range.
Expr * E
The bound expression, or the logical offset for a NumArgs bound.
One item in an OpenMP 'adjust_args' parameter list.
Expr * E
A named parameter or positional expression for a Single item.
llvm::SmallVector< OMPInteropPref, 4 > Prefs
One entry of a prefer_type list.
llvm::SmallVector< Expr *, 2 > Attrs
Iterator definition representation.
SourceLocation AssignmentLoc
SourceLocation SecondColonLoc
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Expr * Upper
Normalized upper bound.
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
VarDecl * CounterVD
Internal normalized counter.
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
std::optional< Expr * > Indirect
The directive with indirect clause.
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
SourceLocation Loc
The directive location.
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Data structure for iterator expression.
int OriginalSharingModifier
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * Allocator
Allocator.