diff options
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 1065 |
1 files changed, 740 insertions, 325 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 920463da4027..78707484f588 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -35,6 +35,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/PointerEmbeddedInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" #include <set> @@ -48,7 +49,7 @@ using namespace llvm::omp; static const Expr *checkMapClauseExpressionBase( Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, - OpenMPClauseKind CKind, bool NoDiagnose); + OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose); namespace { /// Default data sharing attributes, which can be applied to directive. @@ -70,12 +71,15 @@ public: const Expr *RefExpr = nullptr; DeclRefExpr *PrivateCopy = nullptr; SourceLocation ImplicitDSALoc; + bool AppliedToPointee = false; DSAVarData() = default; DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, const Expr *RefExpr, DeclRefExpr *PrivateCopy, - SourceLocation ImplicitDSALoc, unsigned Modifier) + SourceLocation ImplicitDSALoc, unsigned Modifier, + bool AppliedToPointee) : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr), - PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {} + PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc), + AppliedToPointee(AppliedToPointee) {} }; using OperatorOffsetTy = llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>; @@ -99,6 +103,9 @@ private: /// variable is marked as lastprivate(true) or not (false). llvm::PointerIntPair<const Expr *, 1, bool> RefExpr; DeclRefExpr *PrivateCopy = nullptr; + /// true if the attribute is applied to the pointee, not the variable + /// itself. + bool AppliedToPointee = false; }; using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>; using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; @@ -153,6 +160,7 @@ private: OpenMPDirectiveKind Directive = OMPD_unknown; DeclarationNameInfo DirectiveName; Scope *CurScope = nullptr; + DeclContext *Context = nullptr; SourceLocation ConstructLoc; /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to /// get the data (loop counters etc.) about enclosing loop-based construct. @@ -184,6 +192,7 @@ private: llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective; llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind> UsesAllocatorsDecls; + Expr *DeclareMapperVar = nullptr; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) : Directive(DKind), DirectiveName(Name), CurScope(CurScope), @@ -510,7 +519,8 @@ public: /// Adds explicit data sharing attribute to the specified declaration. void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, - DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0); + DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0, + bool AppliedToPointee = false); /// Adds additional information for the reduction items with the reduction id /// represented as an operator. @@ -562,7 +572,8 @@ public: /// match specified \a CPred predicate in any directive which matches \a DPred /// predicate. const DSAVarData - hasDSA(ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + hasDSA(ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const; /// Checks if the specified variables has data-sharing attributes which @@ -570,15 +581,16 @@ public: /// matches \a DPred predicate. const DSAVarData hasInnermostDSA(ValueDecl *D, - const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const; /// Checks if the specified variables has explicit data-sharing /// attributes which match specified \a CPred predicate at the specified /// OpenMP region. - bool hasExplicitDSA(const ValueDecl *D, - const llvm::function_ref<bool(OpenMPClauseKind)> CPred, - unsigned Level, bool NotLastprivate = false) const; + bool + hasExplicitDSA(const ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, + unsigned Level, bool NotLastprivate = false) const; /// Returns true if the directive at level \Level matches in the /// specified \a DPred predicate. @@ -908,6 +920,7 @@ public: const SharingMapTy *Top = getTopOfStackOrNull(); return Top ? Top->CurScope : nullptr; } + void setContext(DeclContext *DC) { getTopOfStack().Context = DC; } SourceLocation getConstructLoc() const { const SharingMapTy *Top = getTopOfStackOrNull(); return Top ? Top->ConstructLoc : SourceLocation(); @@ -1072,6 +1085,15 @@ public: return None; return I->getSecond(); } + + void addDeclareMapperVarRef(Expr *Ref) { + SharingMapTy &StackElem = getTopOfStack(); + StackElem.DeclareMapperVar = Ref; + } + const Expr *getDeclareMapperVarRef() const { + const SharingMapTy *Top = getTopOfStackOrNull(); + return Top ? Top->DeclareMapperVar : nullptr; + } }; bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) { @@ -1175,6 +1197,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter, DVar.CKind = Data.Attributes; DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; DVar.Modifier = Data.Modifier; + DVar.AppliedToPointee = Data.AppliedToPointee; return DVar; } @@ -1331,7 +1354,8 @@ const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const { } void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, - DeclRefExpr *PrivateCopy, unsigned Modifier) { + DeclRefExpr *PrivateCopy, unsigned Modifier, + bool AppliedToPointee) { D = getCanonicalDecl(D); if (A == OMPC_threadprivate) { DSAInfo &Data = Threadprivates[D]; @@ -1355,12 +1379,14 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, Data.Attributes = A; Data.RefExpr.setPointerAndInt(E, IsLastprivate); Data.PrivateCopy = PrivateCopy; + Data.AppliedToPointee = AppliedToPointee; if (PrivateCopy) { DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()]; Data.Modifier = Modifier; Data.Attributes = A; Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); Data.PrivateCopy = nullptr; + Data.AppliedToPointee = AppliedToPointee; } } } @@ -1470,7 +1496,8 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( "set."); TaskgroupDescriptor = I->TaskgroupReductionRef; return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), - Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task); + Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, + /*AppliedToPointee=*/false); } return DSAVarData(); } @@ -1496,7 +1523,8 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( "set."); TaskgroupDescriptor = I->TaskgroupReductionRef; return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(), - Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task); + Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task, + /*AppliedToPointee=*/false); } return DSAVarData(); } @@ -1506,11 +1534,17 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const { for (const_iterator E = end(); I != E; ++I) { if (isImplicitOrExplicitTaskingRegion(I->Directive) || isOpenMPTargetExecutionDirective(I->Directive)) { - Scope *TopScope = I->CurScope ? I->CurScope->getParent() : nullptr; - Scope *CurScope = getCurScope(); - while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D)) - CurScope = CurScope->getParent(); - return CurScope != TopScope; + if (I->CurScope) { + Scope *TopScope = I->CurScope->getParent(); + Scope *CurScope = getCurScope(); + while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D)) + CurScope = CurScope->getParent(); + return CurScope != TopScope; + } + for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) + if (I->Context == DC) + return true; + return false; } } return false; @@ -1665,6 +1699,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, DVar.ImplicitDSALoc = I->DefaultAttrLoc; DVar.DKind = I->Directive; DVar.Modifier = Data.Modifier; + DVar.AppliedToPointee = Data.AppliedToPointee; return DVar; } } @@ -1686,7 +1721,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, // listed in a firstprivate clause, even if they are static data members. DSAVarData DVarTemp = hasInnermostDSA( D, - [](OpenMPClauseKind C) { + [](OpenMPClauseKind C, bool) { return C == OMPC_firstprivate || C == OMPC_shared; }, MatchesAlways, FromParent); @@ -1715,6 +1750,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, DVar.ImplicitDSALoc = I->DefaultAttrLoc; DVar.DKind = I->Directive; DVar.Modifier = Data.Modifier; + DVar.AppliedToPointee = Data.AppliedToPointee; } return DVar; @@ -1745,7 +1781,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D, const DSAStackTy::DSAVarData DSAStackTy::hasDSA(ValueDecl *D, - const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const { if (isStackEmpty()) @@ -1761,14 +1797,14 @@ DSAStackTy::hasDSA(ValueDecl *D, continue; const_iterator NewI = I; DSAVarData DVar = getDSA(NewI, D); - if (I == NewI && CPred(DVar.CKind)) + if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee)) return DVar; } return {}; } const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( - ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred, bool FromParent) const { if (isStackEmpty()) @@ -1782,26 +1818,28 @@ const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA( return {}; const_iterator NewI = StartI; DSAVarData DVar = getDSA(NewI, D); - return (NewI == StartI && CPred(DVar.CKind)) ? DVar : DSAVarData(); + return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee)) + ? DVar + : DSAVarData(); } bool DSAStackTy::hasExplicitDSA( - const ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind)> CPred, + const ValueDecl *D, + const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred, unsigned Level, bool NotLastprivate) const { if (getStackSize() <= Level) return false; D = getCanonicalDecl(D); const SharingMapTy &StackElem = getStackElemAtLevel(Level); auto I = StackElem.SharingMap.find(D); - if (I != StackElem.SharingMap.end() && - I->getSecond().RefExpr.getPointer() && - CPred(I->getSecond().Attributes) && + if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() && + CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) && (!NotLastprivate || !I->getSecond().RefExpr.getInt())) return true; // Check predetermined rules for the loop control variables. auto LI = StackElem.LCVMap.find(D); if (LI != StackElem.LCVMap.end()) - return CPred(OMPC_private); + return CPred(OMPC_private, /*AppliedToPointee=*/false); return false; } @@ -1859,27 +1897,27 @@ enum class FunctionEmissionStatus { }; } // anonymous namespace -Sema::DeviceDiagBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, + unsigned DiagID) { assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice && "Expected OpenMP device compilation."); FunctionDecl *FD = getCurFunctionDecl(); - DeviceDiagBuilder::Kind Kind = DeviceDiagBuilder::K_Nop; + SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; if (FD) { FunctionEmissionStatus FES = getEmissionStatus(FD); switch (FES) { case FunctionEmissionStatus::Emitted: - Kind = DeviceDiagBuilder::K_Immediate; + Kind = SemaDiagnosticBuilder::K_Immediate; break; case FunctionEmissionStatus::Unknown: Kind = isOpenMPDeviceDelayedContext(*this) - ? DeviceDiagBuilder::K_Deferred - : DeviceDiagBuilder::K_Immediate; + ? SemaDiagnosticBuilder::K_Deferred + : SemaDiagnosticBuilder::K_Immediate; break; case FunctionEmissionStatus::TemplateDiscarded: case FunctionEmissionStatus::OMPDiscarded: - Kind = DeviceDiagBuilder::K_Nop; + Kind = SemaDiagnosticBuilder::K_Nop; break; case FunctionEmissionStatus::CUDADiscarded: llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation"); @@ -1887,30 +1925,30 @@ Sema::DeviceDiagBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, } } - return DeviceDiagBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); } -Sema::DeviceDiagBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, + unsigned DiagID) { assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice && "Expected OpenMP host compilation."); FunctionEmissionStatus FES = getEmissionStatus(getCurFunctionDecl()); - DeviceDiagBuilder::Kind Kind = DeviceDiagBuilder::K_Nop; + SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; switch (FES) { case FunctionEmissionStatus::Emitted: - Kind = DeviceDiagBuilder::K_Immediate; + Kind = SemaDiagnosticBuilder::K_Immediate; break; case FunctionEmissionStatus::Unknown: - Kind = DeviceDiagBuilder::K_Deferred; + Kind = SemaDiagnosticBuilder::K_Deferred; break; case FunctionEmissionStatus::TemplateDiscarded: case FunctionEmissionStatus::OMPDiscarded: case FunctionEmissionStatus::CUDADiscarded: - Kind = DeviceDiagBuilder::K_Nop; + Kind = SemaDiagnosticBuilder::K_Nop; break; } - return DeviceDiagBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); } static OpenMPDefaultmapClauseKind @@ -2047,14 +2085,17 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // By default, all the data that has a scalar type is mapped by copy // (except for reduction variables). // Defaultmap scalar is mutual exclusive to defaultmap pointer - IsByRef = - (DSAStack->isForceCaptureByReferenceInTargetExecutable() && - !Ty->isAnyPointerType()) || - !Ty->isScalarType() || - DSAStack->isDefaultmapCapturedByRef( - Level, getVariableCategoryFromDecl(LangOpts, D)) || - DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K == OMPC_reduction; }, Level); + IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() && + !Ty->isAnyPointerType()) || + !Ty->isScalarType() || + DSAStack->isDefaultmapCapturedByRef( + Level, getVariableCategoryFromDecl(LangOpts, D)) || + DSAStack->hasExplicitDSA( + D, + [](OpenMPClauseKind K, bool AppliedToPointee) { + return K == OMPC_reduction && !AppliedToPointee; + }, + Level); } } @@ -2065,8 +2106,9 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, OMPD_target) || !(DSAStack->hasExplicitDSA( D, - [](OpenMPClauseKind K) -> bool { - return K == OMPC_firstprivate; + [](OpenMPClauseKind K, bool AppliedToPointee) -> bool { + return K == OMPC_firstprivate || + (K == OMPC_reduction && AppliedToPointee); }, Level, /*NotLastprivate=*/true) || DSAStack->isUsesAllocatorsDecl(Level, D))) && @@ -2078,7 +2120,8 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // copy !(DSAStack->getDefaultDSA() == DSA_firstprivate && !DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K != OMPC_unknown; }, Level) && + D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; }, + Level) && !DSAStack->isLoopControlVariable(D, Level).first); } @@ -2141,7 +2184,8 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) checkDeclIsAllowedInOpenMPTarget(nullptr, VD); return nullptr; - } else if (isInOpenMPTargetExecutionDirective()) { + } + if (isInOpenMPTargetExecutionDirective()) { // If the declaration is enclosed in a 'declare target' directive, // then it should not be captured. // @@ -2159,6 +2203,7 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, break; } } + assert(CSI && "Failed to find CapturedRegionScopeInfo"); SmallVector<OpenMPDirectiveKind, 4> Regions; getOpenMPCaptureRegions(Regions, DSAStack->getDirective(CSI->OpenMPLevel)); @@ -2194,7 +2239,8 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, return VD ? VD : Info.second; DSAStackTy::DSAVarData DVarTop = DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode()); - if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind)) + if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) && + (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee)) return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl()); // Threadprivate variables must not be captured. if (isOpenMPThreadPrivate(DVarTop.CKind)) @@ -2202,7 +2248,11 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, // The variable is not private or it is the variable in the directive with // default(none) clause and not used in any clause. DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( - D, isOpenMPPrivate, [](OpenMPDirectiveKind) { return true; }, + D, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return isOpenMPPrivate(C) && !AppliedToPointee; + }, + [](OpenMPDirectiveKind) { return true; }, DSAStack->isClauseParsingMode()); // Global shared must not be captured. if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown && @@ -2244,7 +2294,11 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, [](OpenMPDirectiveKind K) { return isOpenMPTaskingDirective(K); }, Level)) { bool IsTriviallyCopyable = - D->getType().getNonReferenceType().isTriviallyCopyableType(Context); + D->getType().getNonReferenceType().isTriviallyCopyableType(Context) && + !D->getType() + .getNonReferenceType() + .getCanonicalType() + ->getAsCXXRecordDecl(); OpenMPDirectiveKind DKind = DSAStack->getDirective(Level); SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; getOpenMPCaptureRegions(CaptureRegions, DKind); @@ -2252,7 +2306,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, (IsTriviallyCopyable || !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) { if (DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K == OMPC_firstprivate; }, + D, + [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; }, Level, /*NotLastprivate=*/true)) return OMPC_firstprivate; DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); @@ -2273,7 +2328,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, if ((DSAStack->getPossiblyLoopCunter() == D->getCanonicalDecl() || DSAStack->isLoopControlVariable(D).first) && !DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K != OMPC_private; }, Level) && + D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; }, + Level) && !isOpenMPSimdDirective(DSAStack->getCurrentDirective())) return OMPC_private; } @@ -2281,7 +2337,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) && DSAStack->isForceVarCapturing() && !DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K == OMPC_copyin; }, Level)) + D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; }, + Level)) return OMPC_private; } // User-defined allocators are private since they must be defined in the @@ -2292,7 +2349,8 @@ OpenMPClauseKind Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator) return OMPC_private; return (DSAStack->hasExplicitDSA( - D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) || + D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; }, + Level) || (DSAStack->isClauseParsingMode() && DSAStack->getClauseParsingMode() == OMPC_private) || // Consider taskgroup reduction descriptor variable a private @@ -2317,15 +2375,16 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, OpenMPClauseKind OMPC = OMPC_unknown; for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) { const unsigned NewLevel = I - 1; - if (DSAStack->hasExplicitDSA(D, - [&OMPC](const OpenMPClauseKind K) { - if (isOpenMPPrivate(K)) { - OMPC = K; - return true; - } - return false; - }, - NewLevel)) + if (DSAStack->hasExplicitDSA( + D, + [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) { + if (isOpenMPPrivate(K) && !AppliedToPointee) { + OMPC = K; + return true; + } + return false; + }, + NewLevel)) break; if (DSAStack->checkMappableExprComponentListsForDeclAtLevel( D, NewLevel, @@ -2368,17 +2427,20 @@ bool Sema::isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, if (const auto *VD = dyn_cast<VarDecl>(D)) { if (!VD->hasLocalStorage()) { + if (isInOpenMPTargetExecutionDirective()) + return true; DSAStackTy::DSAVarData TopDVar = DSAStack->getTopDSA(D, /*FromParent=*/false); unsigned NumLevels = getOpenMPCaptureLevels(DSAStack->getDirective(Level)); if (Level == 0) return (NumLevels == CaptureLevel + 1) && TopDVar.CKind != OMPC_shared; - DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level - 1); - return DVar.CKind != OMPC_shared || - isOpenMPGlobalCapturedDecl( - D, Level - 1, - getOpenMPCaptureLevels(DSAStack->getDirective(Level - 1)) - 1); + do { + --Level; + DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level); + if (DVar.CKind != OMPC_shared) + return true; + } while (Level > 0); } } return true; @@ -2388,10 +2450,6 @@ void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; } void Sema::ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI) { - if (!OMPDeclareVariantScopes.empty()) { - Diag(Loc, diag::warn_nested_declare_variant); - return; - } OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI)); } @@ -2424,7 +2482,7 @@ void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, StringRef HostDevTy = getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host); Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0; - Diag(FD->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(), + Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), diag::note_omp_marked_device_type_here) << HostDevTy; return; @@ -2435,7 +2493,7 @@ void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName( OMPC_device_type, OMPC_DEVICE_TYPE_nohost); Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1; - Diag(FD->getAttr<OMPDeclareTargetDeclAttr>()->getLocation(), + Diag(*OMPDeclareTargetDeclAttr::getLocation(FD), diag::note_omp_marked_device_type_here) << NoHostDevTy; } @@ -3138,6 +3196,64 @@ Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc, return DeclGroupPtrTy::make(DeclGroupRef(D)); } +void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc, + OpenMPDirectiveKind DKind, + ArrayRef<StringRef> Assumptions, + bool SkippedClauses) { + if (!SkippedClauses && Assumptions.empty()) + Diag(Loc, diag::err_omp_no_clause_for_directive) + << llvm::omp::getAllAssumeClauseOptions() + << llvm::omp::getOpenMPDirectiveName(DKind); + + auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc); + if (DKind == llvm::omp::Directive::OMPD_begin_assumes) { + OMPAssumeScoped.push_back(AA); + return; + } + + // Global assumes without assumption clauses are ignored. + if (Assumptions.empty()) + return; + + assert(DKind == llvm::omp::Directive::OMPD_assumes && + "Unexpected omp assumption directive!"); + OMPAssumeGlobal.push_back(AA); + + // The OMPAssumeGlobal scope above will take care of new declarations but + // we also want to apply the assumption to existing ones, e.g., to + // declarations in included headers. To this end, we traverse all existing + // declaration contexts and annotate function declarations here. + SmallVector<DeclContext *, 8> DeclContexts; + auto *Ctx = CurContext; + while (Ctx->getLexicalParent()) + Ctx = Ctx->getLexicalParent(); + DeclContexts.push_back(Ctx); + while (!DeclContexts.empty()) { + DeclContext *DC = DeclContexts.pop_back_val(); + for (auto *SubDC : DC->decls()) { + if (SubDC->isInvalidDecl()) + continue; + if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) { + DeclContexts.push_back(CTD->getTemplatedDecl()); + for (auto *S : CTD->specializations()) + DeclContexts.push_back(S); + continue; + } + if (auto *DC = dyn_cast<DeclContext>(SubDC)) + DeclContexts.push_back(DC); + if (auto *F = dyn_cast<FunctionDecl>(SubDC)) { + F->addAttr(AA); + continue; + } + } + } +} + +void Sema::ActOnOpenMPEndAssumesDirective() { + assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!"); + OMPAssumeScoped.pop_back(); +} + OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef<OMPClause *> ClauseList) { /// For target specific clauses, the requires directive cannot be @@ -3249,6 +3365,14 @@ getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, case OMPC_DEFAULTMAP_MODIFIER_tofrom: Kind = OMPC_MAP_tofrom; break; + case OMPC_DEFAULTMAP_MODIFIER_present: + // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description] + // If implicit-behavior is present, each variable referenced in the + // construct in the category specified by variable-category is treated as if + // it had been listed in a map clause with the map-type of alloc and + // map-type-modifier of present. + Kind = OMPC_MAP_alloc; + break; case OMPC_DEFAULTMAP_MODIFIER_firstprivate: case OMPC_DEFAULTMAP_MODIFIER_last: llvm_unreachable("Unexpected defaultmap implicit behavior"); @@ -3275,8 +3399,11 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { bool ErrorFound = false; bool TryCaptureCXXThisMembers = false; CapturedStmt *CS = nullptr; + const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1; llvm::SmallVector<Expr *, 4> ImplicitFirstprivate; - llvm::SmallVector<Expr *, 4> ImplicitMap[OMPC_MAP_delete]; + llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete]; + llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers> + ImplicitMapModifier[DefaultmapKindNum]; Sema::VarsWithInheritedDSAType VarsWithInheritedDSA; llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations; @@ -3284,6 +3411,13 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { // Check implicitly captured variables. if (!S->hasAssociatedStmt() || !S->getAssociatedStmt()) return; + if (S->getDirectiveKind() == OMPD_atomic || + S->getDirectiveKind() == OMPD_critical || + S->getDirectiveKind() == OMPD_section || + S->getDirectiveKind() == OMPD_master) { + Visit(S->getAssociatedStmt()); + return; + } visitSubCaptures(S->getInnermostCapturedStmt()); // Try to capture inner this->member references to generate correct mappings // and diagnostics. @@ -3405,6 +3539,18 @@ public: } } } + if (SemaRef.getLangOpts().OpenMP > 50) { + bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) == + OMPC_DEFAULTMAP_MODIFIER_present; + if (IsModifierPresent) { + if (llvm::find(ImplicitMapModifier[ClauseKind], + OMPC_MAP_MODIFIER_present) == + std::end(ImplicitMapModifier[ClauseKind])) { + ImplicitMapModifier[ClauseKind].push_back( + OMPC_MAP_MODIFIER_present); + } + } + } if (isOpenMPTargetExecutionDirective(DKind) && !Stack->isLoopControlVariable(VD).first) { @@ -3445,7 +3591,7 @@ public: Stack->getDefaultmapModifier(ClauseKind); OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res); - ImplicitMap[Kind].emplace_back(E); + ImplicitMap[ClauseKind][Kind].emplace_back(E); } return; } @@ -3456,7 +3602,10 @@ public: // enclosing worksharing or parallel construct may not be accessed in an // explicit task. DVar = Stack->hasInnermostDSA( - VD, [](OpenMPClauseKind C) { return C == OMPC_reduction; }, + VD, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return C == OMPC_reduction && !AppliedToPointee; + }, [](OpenMPDirectiveKind K) { return isOpenMPParallelDirective(K) || isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); @@ -3529,9 +3678,11 @@ public: OpenMPDefaultmapClauseModifier Modifier = Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate); + OpenMPDefaultmapClauseKind ClauseKind = + getVariableCategoryFromDecl(SemaRef.getLangOpts(), FD); OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( Modifier, /*IsAggregateOrDeclareTarget*/ true); - ImplicitMap[Kind].emplace_back(E); + ImplicitMap[ClauseKind][Kind].emplace_back(E); return; } @@ -3541,7 +3692,10 @@ public: // enclosing worksharing or parallel construct may not be accessed in // an explicit task. DVar = Stack->hasInnermostDSA( - FD, [](OpenMPClauseKind C) { return C == OMPC_reduction; }, + FD, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return C == OMPC_reduction && !AppliedToPointee; + }, [](OpenMPDirectiveKind K) { return isOpenMPParallelDirective(K) || isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K); @@ -3570,6 +3724,7 @@ public: if (isOpenMPTargetExecutionDirective(DKind)) { OMPClauseMappableExprCommon::MappableExprComponentList CurComponents; if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map, + Stack->getCurrentDirective(), /*NoDiagnose=*/true)) return; const auto *VD = cast<ValueDecl>( @@ -3619,7 +3774,8 @@ public: // Skip analysis of arguments of implicitly defined map clause for target // directives. if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) && - C->isImplicit())) { + C->isImplicit() && + !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) { for (Stmt *CC : C->children()) { if (CC) Visit(CC); @@ -3662,8 +3818,13 @@ public: ArrayRef<Expr *> getImplicitFirstprivate() const { return ImplicitFirstprivate; } - ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind Kind) const { - return ImplicitMap[Kind]; + ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind DK, + OpenMPMapClauseKind MK) const { + return ImplicitMap[DK][MK]; + } + ArrayRef<OpenMPMapModifierKind> + getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const { + return ImplicitMapModifier[Kind]; } const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const { return VarsWithInheritedDSA; @@ -3784,19 +3945,20 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { /*OpenMPCaptureLevel=*/1); break; } + case OMPD_atomic: + case OMPD_critical: + case OMPD_section: + case OMPD_master: + break; case OMPD_simd: case OMPD_for: case OMPD_for_simd: case OMPD_sections: - case OMPD_section: case OMPD_single: - case OMPD_master: - case OMPD_critical: case OMPD_taskgroup: case OMPD_distribute: case OMPD_distribute_simd: case OMPD_ordered: - case OMPD_atomic: case OMPD_target_data: { Sema::CapturedParamNameType Params[] = { std::make_pair(StringRef(), QualType()) // __context with shared vars @@ -4088,6 +4250,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { default: llvm_unreachable("Unknown OpenMP directive"); } + DSAStack->setContext(CurContext); } int Sema::getNumberOfConstructScopes(unsigned Level) const { @@ -4125,6 +4288,7 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id, if (!WithInit) CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C)); S.CurContext->addHiddenDecl(CED); + Sema::TentativeAnalysisScope Trap(S); S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false); return CED; } @@ -4262,6 +4426,12 @@ static bool checkOrderedOrderSpecified(Sema &S, StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S, ArrayRef<OMPClause *> Clauses) { + if (DSAStack->getCurrentDirective() == OMPD_atomic || + DSAStack->getCurrentDirective() == OMPD_critical || + DSAStack->getCurrentDirective() == OMPD_section || + DSAStack->getCurrentDirective() == OMPD_master) + return S; + bool ErrorFound = false; CaptureRegionUnwinderRAII CaptureRegionUnwinder( *this, ErrorFound, DSAStack->getCurrentDirective()); @@ -4975,7 +5145,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( VarsWithInheritedDSAType VarsWithInheritedDSA; bool ErrorFound = false; ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); - if (AStmt && !CurContext->isDependentContext()) { + if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic && + Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master) { assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); // Check default data sharing attributes for referenced variables. @@ -5004,11 +5175,33 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( SmallVector<Expr *, 4> ImplicitFirstprivates( DSAChecker.getImplicitFirstprivate().begin(), DSAChecker.getImplicitFirstprivate().end()); - SmallVector<Expr *, 4> ImplicitMaps[OMPC_MAP_delete]; - for (unsigned I = 0; I < OMPC_MAP_delete; ++I) { - ArrayRef<Expr *> ImplicitMap = - DSAChecker.getImplicitMap(static_cast<OpenMPDefaultmapClauseKind>(I)); - ImplicitMaps[I].append(ImplicitMap.begin(), ImplicitMap.end()); + const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_pointer + 1; + SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete]; + SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers> + ImplicitMapModifiers[DefaultmapKindNum]; + SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers> + ImplicitMapModifiersLoc[DefaultmapKindNum]; + // Get the original location of present modifier from Defaultmap clause. + SourceLocation PresentModifierLocs[DefaultmapKindNum]; + for (OMPClause *C : Clauses) { + if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C)) + if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present) + PresentModifierLocs[DMC->getDefaultmapKind()] = + DMC->getDefaultmapModifierLoc(); + } + for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) { + auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC); + for (unsigned I = 0; I < OMPC_MAP_delete; ++I) { + ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap( + Kind, static_cast<OpenMPMapClauseKind>(I)); + ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end()); + } + ArrayRef<OpenMPMapModifierKind> ImplicitModifier = + DSAChecker.getImplicitMapModifier(Kind); + ImplicitMapModifiers[VC].append(ImplicitModifier.begin(), + ImplicitModifier.end()); + std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]), + ImplicitModifier.size(), PresentModifierLocs[VC]); } // Mark taskgroup task_reduction descriptors as implicitly firstprivate. for (OMPClause *C : Clauses) { @@ -5034,23 +5227,26 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( ErrorFound = true; } } - int ClauseKindCnt = -1; - for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps) { - ++ClauseKindCnt; - if (ImplicitMap.empty()) - continue; - CXXScopeSpec MapperIdScopeSpec; - DeclarationNameInfo MapperId; - auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt); - if (OMPClause *Implicit = ActOnOpenMPMapClause( - llvm::None, llvm::None, MapperIdScopeSpec, MapperId, Kind, - /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), - ImplicitMap, OMPVarListLocTy())) { - ClausesWithImplicit.emplace_back(Implicit); - ErrorFound |= - cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMap.size(); - } else { - ErrorFound = true; + for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) { + int ClauseKindCnt = -1; + for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) { + ++ClauseKindCnt; + if (ImplicitMap.empty()) + continue; + CXXScopeSpec MapperIdScopeSpec; + DeclarationNameInfo MapperId; + auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt); + if (OMPClause *Implicit = ActOnOpenMPMapClause( + ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I], + MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true, + SourceLocation(), SourceLocation(), ImplicitMap, + OMPVarListLocTy())) { + ClausesWithImplicit.emplace_back(Implicit); + ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() != + ImplicitMap.size(); + } else { + ErrorFound = true; + } } } } @@ -5760,7 +5956,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step) .get(); if (NewStep) - NewStep = VerifyIntegerConstantExpression(NewStep).get(); + NewStep = + VerifyIntegerConstantExpression(NewStep, /*FIXME*/ AllowFold).get(); } NewSteps.push_back(NewStep); } @@ -5798,12 +5995,45 @@ static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, FD->setParams(Params); } +void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) { + if (D->isInvalidDecl()) + return; + FunctionDecl *FD = nullptr; + if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D)) + FD = UTemplDecl->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(D); + assert(FD && "Expected a function declaration!"); + + // If we are intantiating templates we do *not* apply scoped assumptions but + // only global ones. We apply scoped assumption to the template definition + // though. + if (!inTemplateInstantiation()) { + for (AssumptionAttr *AA : OMPAssumeScoped) + FD->addAttr(AA); + } + for (AssumptionAttr *AA : OMPAssumeGlobal) + FD->addAttr(AA); +} + Sema::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI) : TI(&TI), NameSuffix(TI.getMangledName()) {} -FunctionDecl * -Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, - Declarator &D) { +void Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( + Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, + SmallVectorImpl<FunctionDecl *> &Bases) { + if (!D.getIdentifier()) + return; + + OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); + + // Template specialization is an extension, check if we do it. + bool IsTemplated = !TemplateParamLists.empty(); + if (IsTemplated & + !DVScope.TI->isExtensionActive( + llvm::omp::TraitProperty::implementation_extension_allow_templates)) + return; + IdentifierInfo *BaseII = D.getIdentifier(); LookupResult Lookup(*this, DeclarationName(BaseII), D.getIdentifierLoc(), LookupOrdinaryName); @@ -5812,12 +6042,18 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType FType = TInfo->getType(); - bool IsConstexpr = D.getDeclSpec().getConstexprSpecifier() == CSK_constexpr; - bool IsConsteval = D.getDeclSpec().getConstexprSpecifier() == CSK_consteval; + bool IsConstexpr = + D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr; + bool IsConsteval = + D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval; - FunctionDecl *BaseFD = nullptr; for (auto *Candidate : Lookup) { - auto *UDecl = dyn_cast<FunctionDecl>(Candidate->getUnderlyingDecl()); + auto *CandidateDecl = Candidate->getUnderlyingDecl(); + FunctionDecl *UDecl = nullptr; + if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) + UDecl = cast<FunctionTemplateDecl>(CandidateDecl)->getTemplatedDecl(); + else if (!IsTemplated) + UDecl = dyn_cast<FunctionDecl>(CandidateDecl); if (!UDecl) continue; @@ -5828,22 +6064,32 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, if (UDecl->isConsteval() && !IsConsteval) continue; - QualType NewType = Context.mergeFunctionTypes( - FType, UDecl->getType(), /* OfBlockPointer */ false, - /* Unqualified */ false, /* AllowCXX */ true); - if (NewType.isNull()) - continue; + QualType UDeclTy = UDecl->getType(); + if (!UDeclTy->isDependentType()) { + QualType NewType = Context.mergeFunctionTypes( + FType, UDeclTy, /* OfBlockPointer */ false, + /* Unqualified */ false, /* AllowCXX */ true); + if (NewType.isNull()) + continue; + } // Found a base! - BaseFD = UDecl; - break; - } - if (!BaseFD) { - BaseFD = cast<FunctionDecl>(ActOnDeclarator(S, D)); - BaseFD->setImplicit(true); + Bases.push_back(UDecl); + } + + bool UseImplicitBase = !DVScope.TI->isExtensionActive( + llvm::omp::TraitProperty::implementation_extension_disable_implicit_base); + // If no base was found we create a declaration that we use as base. + if (Bases.empty() && UseImplicitBase) { + D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration); + Decl *BaseD = HandleDeclarator(S, D, TemplateParamLists); + BaseD->setImplicit(true); + if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD)) + Bases.push_back(BaseTemplD->getTemplatedDecl()); + else + Bases.push_back(cast<FunctionDecl>(BaseD)); } - OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); std::string MangledName; MangledName += D.getIdentifier()->getName(); MangledName += getOpenMPVariantManglingSeparatorStr(); @@ -5852,17 +6098,21 @@ Sema::ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, VariantII.setMangledOpenMPVariantName(true); D.SetIdentifier(&VariantII, D.getBeginLoc()); - return BaseFD; } void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( - FunctionDecl *FD, FunctionDecl *BaseFD) { + Decl *D, SmallVectorImpl<FunctionDecl *> &Bases) { // Do not mark function as is used to prevent its emission if this is the // only place where it is used. EnterExpressionEvaluationContext Unevaluated( *this, Sema::ExpressionEvaluationContext::Unevaluated); - Expr *VariantFuncRef = DeclRefExpr::Create( + FunctionDecl *FD = nullptr; + if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D)) + FD = UTemplDecl->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(D); + auto *VariantFuncRef = DeclRefExpr::Create( Context, NestedNameSpecifierLoc(), SourceLocation(), FD, /* RefersToEnclosingVariableOrCapture */ false, /* NameLoc */ FD->getLocation(), FD->getType(), ExprValueKind::VK_RValue); @@ -5870,7 +6120,8 @@ void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back(); auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit( Context, VariantFuncRef, DVScope.TI); - BaseFD->addAttr(OMPDeclareVariantA); + for (FunctionDecl *BaseFD : Bases) + BaseFD->addAttr(OMPDeclareVariantA); } ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, @@ -5891,8 +6142,17 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, return Call; ASTContext &Context = getASTContext(); - OMPContext OMPCtx(getLangOpts().OpenMPIsDevice, - Context.getTargetInfo().getTriple()); + std::function<void(StringRef)> DiagUnknownTrait = [this, + CE](StringRef ISATrait) { + // TODO Track the selector locations in a way that is accessible here to + // improve the diagnostic location. + Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait) + << ISATrait; + }; + TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait), + getCurFunctionDecl()); + + QualType CalleeFnType = CalleeFnDecl->getType(); SmallVector<Expr *, 4> Exprs; SmallVector<VariantMatchInfo, 4> VMIs; @@ -5904,7 +6164,8 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, VariantMatchInfo VMI; OMPTraitInfo &TI = A->getTraitInfo(); TI.getAsVariantMatchInfo(Context, VMI); - if (!isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ false)) + if (!isVariantApplicableInContext(VMI, OMPCtx, + /* DeviceSetOnly */ false)) continue; VMIs.push_back(VMI); @@ -5945,8 +6206,19 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, } NewCall = BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs, RParenLoc, ExecConfig); - if (NewCall.isUsable()) - break; + if (NewCall.isUsable()) { + if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) { + FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee(); + QualType NewType = Context.mergeFunctionTypes( + CalleeFnType, NewCalleeFnDecl->getType(), + /* OfBlockPointer */ false, + /* Unqualified */ false, /* AllowCXX */ true); + if (!NewType.isNull()) + break; + // Don't use the call if the function type was not compatible. + NewCall = nullptr; + } + } } VMIs.erase(VMIs.begin() + BestIdx); @@ -6027,8 +6299,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, // Deal with non-constant score and user condition expressions. auto HandleNonConstantScoresAndConditions = [this](Expr *&E, bool IsScore) -> bool { - llvm::APSInt Result; - if (!E || E->isIntegerConstantExpr(Result, Context)) + if (!E || E->isIntegerConstantExpr(Context)) return false; if (IsScore) { @@ -6051,7 +6322,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, // Convert VariantRef expression to the type of the original function to // resolve possible conflicts. - ExprResult VariantRefCast; + ExprResult VariantRefCast = VariantRef; if (LangOpts.CPlusPlus) { QualType FnPtrType; auto *Method = dyn_cast<CXXMethodDecl>(FD); @@ -6076,25 +6347,27 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, } else { FnPtrType = Context.getPointerType(FD->getType()); } - ImplicitConversionSequence ICS = - TryImplicitConversion(VariantRef, FnPtrType.getUnqualifiedType(), - /*SuppressUserConversions=*/false, - AllowedExplicit::None, - /*InOverloadResolution=*/false, - /*CStyle=*/false, - /*AllowObjCWritebackConversion=*/false); - if (ICS.isFailure()) { - Diag(VariantRef->getExprLoc(), - diag::err_omp_declare_variant_incompat_types) - << VariantRef->getType() - << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType()) - << VariantRef->getSourceRange(); - return None; + QualType VarianPtrType = Context.getPointerType(VariantRef->getType()); + if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) { + ImplicitConversionSequence ICS = TryImplicitConversion( + VariantRef, FnPtrType.getUnqualifiedType(), + /*SuppressUserConversions=*/false, AllowedExplicit::None, + /*InOverloadResolution=*/false, + /*CStyle=*/false, + /*AllowObjCWritebackConversion=*/false); + if (ICS.isFailure()) { + Diag(VariantRef->getExprLoc(), + diag::err_omp_declare_variant_incompat_types) + << VariantRef->getType() + << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType()) + << VariantRef->getSourceRange(); + return None; + } + VariantRefCast = PerformImplicitConversion( + VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting); + if (!VariantRefCast.isUsable()) + return None; } - VariantRefCast = PerformImplicitConversion( - VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting); - if (!VariantRefCast.isUsable()) - return None; // Drop previously built artificial addr_of unary op for member functions. if (Method && !Method->isStatic()) { Expr *PossibleAddrOfVariantRef = VariantRefCast.get(); @@ -6102,8 +6375,6 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, PossibleAddrOfVariantRef->IgnoreImplicit())) VariantRefCast = UO->getSubExpr(); } - } else { - VariantRefCast = VariantRef; } ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get()); @@ -6514,14 +6785,14 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { // loop. If test-expr is of form b relational-op var and relational-op is // > or >= then incr-expr must cause var to increase on each iteration of // the loop. - llvm::APSInt Result; - bool IsConstant = NewStep->isIntegerConstantExpr(Result, SemaRef.Context); + Optional<llvm::APSInt> Result = + NewStep->getIntegerConstantExpr(SemaRef.Context); bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation(); bool IsConstNeg = - IsConstant && Result.isSigned() && (Subtract != Result.isNegative()); + Result && Result->isSigned() && (Subtract != Result->isNegative()); bool IsConstPos = - IsConstant && Result.isSigned() && (Subtract == Result.isNegative()); - bool IsConstZero = IsConstant && !Result.getBoolValue(); + Result && Result->isSigned() && (Subtract == Result->isNegative()); + bool IsConstZero = Result && !Result->getBoolValue(); // != with increment is treated as <; != with decrement is treated as > if (!TestIsLessOp.hasValue()) @@ -6969,9 +7240,16 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures); if (!NewStep.isUsable()) return nullptr; - llvm::APSInt LRes, URes, SRes; - bool IsLowerConst = Lower->isIntegerConstantExpr(LRes, SemaRef.Context); - bool IsStepConst = Step->isIntegerConstantExpr(SRes, SemaRef.Context); + llvm::APSInt LRes, SRes; + bool IsLowerConst = false, IsStepConst = false; + if (Optional<llvm::APSInt> Res = Lower->getIntegerConstantExpr(SemaRef.Context)) { + LRes = *Res; + IsLowerConst = true; + } + if (Optional<llvm::APSInt> Res = Step->getIntegerConstantExpr(SemaRef.Context)) { + SRes = *Res; + IsStepConst = true; + } bool NoNeedToConvert = IsLowerConst && !RoundToStep && ((!TestIsStrictOp && LRes.isNonNegative()) || (TestIsStrictOp && LRes.isStrictlyPositive())); @@ -7004,7 +7282,12 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, } NeedToReorganize = NoNeedToConvert; } - bool IsUpperConst = Upper->isIntegerConstantExpr(URes, SemaRef.Context); + llvm::APSInt URes; + bool IsUpperConst = false; + if (Optional<llvm::APSInt> Res = Upper->getIntegerConstantExpr(SemaRef.Context)) { + URes = *Res; + IsUpperConst = true; + } if (NoNeedToConvert && IsLowerConst && IsUpperConst && (!RoundToStep || IsStepConst)) { unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth() @@ -7436,6 +7719,7 @@ std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues( if (!Diff.isUsable()) return std::make_pair(nullptr, nullptr); + Sema::TentativeAnalysisScope Trap(SemaRef); Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false); if (!Diff.isUsable()) return std::make_pair(nullptr, nullptr); @@ -7952,9 +8236,9 @@ static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) { static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) { if (E == nullptr) return false; - llvm::APSInt Result; - if (E->isIntegerConstantExpr(Result, SemaRef.Context)) - return Signed ? Result.isSignedIntN(Bits) : Result.isIntN(Bits); + if (Optional<llvm::APSInt> Result = + E->getIntegerConstantExpr(SemaRef.Context)) + return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits); return false; } @@ -8227,9 +8511,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Calculate the last iteration number beforehand instead of doing this on // each iteration. Do not do this if the number of iterations may be kfold-ed. - llvm::APSInt Result; - bool IsConstant = - LastIteration.get()->isIntegerConstantExpr(Result, SemaRef.Context); + bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context); ExprResult CalcLastIteration; if (!IsConstant) { ExprResult SaveRef = @@ -8915,8 +9197,6 @@ StmtResult Sema::ActOnOpenMPSectionDirective(Stmt *AStmt, if (!AStmt) return StmtError(); - assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); - setFunctionHasBranchProtectedScope(); DSAStack->setParentCancelRegion(DSAStack->isCancelRegion()); @@ -8961,8 +9241,6 @@ StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt, if (!AStmt) return StmtError(); - assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); - setFunctionHasBranchProtectedScope(); return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt); @@ -8974,8 +9252,6 @@ StmtResult Sema::ActOnOpenMPCriticalDirective( if (!AStmt) return StmtError(); - assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); - bool ErrorFound = false; llvm::APSInt Hint; SourceLocation HintLoc; @@ -9693,7 +9969,6 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, if (!AStmt) return StmtError(); - auto *CS = cast<CapturedStmt>(AStmt); // 1.2.2 OpenMP Language Terminology // Structured block - An executable statement with a single entry at the // top and a single exit at the bottom. @@ -9757,7 +10032,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, << getOpenMPClauseName(MemOrderKind); } - Stmt *Body = CS->getCapturedStmt(); + Stmt *Body = AStmt; if (auto *EWC = dyn_cast<ExprWithCleanups>(Body)) Body = EWC->getSubExpr(); @@ -12620,15 +12895,16 @@ isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, ValExpr = Value.get(); // The expression must evaluate to a non-negative integer value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) && - Result.isSigned() && - !((!StrictlyPositive && Result.isNonNegative()) || - (StrictlyPositive && Result.isStrictlyPositive()))) { - SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) - << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) - << ValExpr->getSourceRange(); - return false; + if (Optional<llvm::APSInt> Result = + ValExpr->getIntegerConstantExpr(SemaRef.Context)) { + if (Result->isSigned() && + !((!StrictlyPositive && Result->isNonNegative()) || + (StrictlyPositive && Result->isStrictlyPositive()))) { + SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) + << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) + << ValExpr->getSourceRange(); + return false; + } } if (!BuildCapture) return true; @@ -12681,7 +12957,8 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) return E; llvm::APSInt Result; - ExprResult ICE = VerifyIntegerConstantExpression(E, &Result); + ExprResult ICE = + VerifyIntegerConstantExpression(E, &Result, /*FIXME*/ AllowFold); if (ICE.isInvalid()) return ExprError(); if ((StrictlyPositive && !Result.isStrictlyPositive()) || @@ -13263,9 +13540,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, Context)) { - if (Result.isSigned() && !Result.isStrictlyPositive()) { + if (Optional<llvm::APSInt> Result = + ValExpr->getIntegerConstantExpr(Context)) { + if (Result->isSigned() && !Result->isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) << "schedule" << 1 << ChunkSize->getSourceRange(); return nullptr; @@ -13522,7 +13799,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause( DeclarationNameInfo &ReductionOrMapperId, int ExtraModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, ArrayRef<SourceLocation> MapTypeModifiersLoc, bool IsMapTypeImplicit, - SourceLocation ExtraModifierLoc) { + SourceLocation ExtraModifierLoc, + ArrayRef<OpenMPMotionModifierKind> MotionModifiers, + ArrayRef<SourceLocation> MotionModifiersLoc) { SourceLocation StartLoc = Locs.StartLoc; SourceLocation LParenLoc = Locs.LParenLoc; SourceLocation EndLoc = Locs.EndLoc; @@ -13599,12 +13878,14 @@ OMPClause *Sema::ActOnOpenMPVarListClause( IsMapTypeImplicit, ExtraModifierLoc, ColonLoc, VarList, Locs); break; case OMPC_to: - Res = ActOnOpenMPToClause(VarList, ReductionOrMapperIdScopeSpec, - ReductionOrMapperId, Locs); + Res = ActOnOpenMPToClause(MotionModifiers, MotionModifiersLoc, + ReductionOrMapperIdScopeSpec, ReductionOrMapperId, + ColonLoc, VarList, Locs); break; case OMPC_from: - Res = ActOnOpenMPFromClause(VarList, ReductionOrMapperIdScopeSpec, - ReductionOrMapperId, Locs); + Res = ActOnOpenMPFromClause(MotionModifiers, MotionModifiersLoc, + ReductionOrMapperIdScopeSpec, + ReductionOrMapperId, ColonLoc, VarList, Locs); break; case OMPC_use_device_ptr: Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs); @@ -14003,7 +14284,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, // from the worksharing construct. if (isOpenMPTaskingDirective(CurrDir)) { DVar = DSAStack->hasInnermostDSA( - D, [](OpenMPClauseKind C) { return C == OMPC_reduction; }, + D, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return C == OMPC_reduction && !AppliedToPointee; + }, [](OpenMPDirectiveKind K) { return isOpenMPParallelDirective(K) || isOpenMPWorksharingDirective(K) || @@ -14296,7 +14580,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause( if (!isOpenMPCapturedDecl(D)) ExprCaptures.push_back(Ref->getDecl()); } - if (TopDVar.CKind == OMPC_firstprivate || + if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) || (!isOpenMPCapturedDecl(D) && Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) { ExprResult RefRes = DefaultLvalueConversion(Ref); @@ -14394,7 +14678,11 @@ public: if (DVar.CKind != OMPC_unknown) return true; DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA( - VD, isOpenMPPrivate, [](OpenMPDirectiveKind) { return true; }, + VD, + [](OpenMPClauseKind C, bool AppliedToPointee) { + return isOpenMPPrivate(C) && !AppliedToPointee; + }, + [](OpenMPDirectiveKind) { return true; }, /*FromParent=*/true); return DVarPrivate.CKind != OMPC_unknown; } @@ -15027,6 +15315,17 @@ static bool actOnOMPReductionKindClause( continue; } } + } else { + // Threadprivates cannot be shared between threads, so dignose if the base + // is a threadprivate variable. + DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false); + if (DVar.CKind == OMPC_threadprivate) { + S.Diag(ELoc, diag::err_omp_wrong_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPClauseName(OMPC_reduction); + reportOriginalDsa(S, Stack, D, DVar); + continue; + } } // Try to find 'declare reduction' corresponding construct before using @@ -15153,6 +15452,7 @@ static bool actOnOMPReductionKindClause( auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>(); auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl()); if (DRD->getInitializer()) { + S.ActOnUninitializedDecl(PrivateVD); Init = DRDRef; RHSVD->setInit(DRDRef); RHSVD->setInitStyle(VarDecl::CallInit); @@ -15259,10 +15559,19 @@ static bool actOnOMPReductionKindClause( llvm_unreachable("Unexpected reduction operation"); } } - if (Init && DeclareReductionRef.isUnset()) + if (Init && DeclareReductionRef.isUnset()) { S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false); - else if (!Init) + // Store initializer for single element in private copy. Will be used + // during codegen. + PrivateVD->setInit(RHSVD->getInit()); + PrivateVD->setInitStyle(RHSVD->getInitStyle()); + } else if (!Init) { S.ActOnUninitializedDecl(RHSVD); + // Store initializer for single element in private copy. Will be used + // during codegen. + PrivateVD->setInit(RHSVD->getInit()); + PrivateVD->setInitStyle(RHSVD->getInitStyle()); + } if (RHSVD->isInvalidDecl()) continue; if (!RHSVD->hasInit() && @@ -15276,10 +15585,6 @@ static bool actOnOMPReductionKindClause( << D; continue; } - // Store initializer for single element in private copy. Will be used during - // codegen. - PrivateVD->setInit(RHSVD->getInit()); - PrivateVD->setInitStyle(RHSVD->getInitStyle()); DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc); ExprResult ReductionOp; if (DeclareReductionRef.isUsable()) { @@ -15290,12 +15595,12 @@ static bool actOnOMPReductionKindClause( if (!BasePath.empty()) { LHS = S.DefaultLvalueConversion(LHS.get()); RHS = S.DefaultLvalueConversion(RHS.get()); - LHS = ImplicitCastExpr::Create(Context, PtrRedTy, - CK_UncheckedDerivedToBase, LHS.get(), - &BasePath, LHS.get()->getValueKind()); - RHS = ImplicitCastExpr::Create(Context, PtrRedTy, - CK_UncheckedDerivedToBase, RHS.get(), - &BasePath, RHS.get()->getValueKind()); + LHS = ImplicitCastExpr::Create( + Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath, + LHS.get()->getValueKind(), FPOptionsOverride()); + RHS = ImplicitCastExpr::Create( + Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath, + RHS.get()->getValueKind(), FPOptionsOverride()); } FunctionProtoType::ExtProtoInfo EPI; QualType Params[] = {PtrRedTy, PtrRedTy}; @@ -15305,7 +15610,8 @@ static bool actOnOMPReductionKindClause( S.DefaultLvalueConversion(DeclareReductionRef.get()).get()); Expr *Args[] = {LHS.get(), RHS.get()}; ReductionOp = - CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc); + CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc, + S.CurFPFeatureOverrides()); } else { ReductionOp = S.BuildBinOp( Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE); @@ -15465,7 +15771,8 @@ static bool actOnOMPReductionKindClause( // correct analysis of in_reduction clauses. if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction) Modifier = OMPC_REDUCTION_task; - Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier); + Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier, + ASE || OASE); if (Modifier == OMPC_REDUCTION_task && (CurrDir == OMPD_taskgroup || ((isOpenMPParallelDirective(CurrDir) || @@ -15736,12 +16043,12 @@ OMPClause *Sema::ActOnOpenMPLinearClause( // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). - llvm::APSInt Result; - bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context); - if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive()) - Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0] - << (Vars.size() > 1); - if (!IsConstant && CalcStep.isUsable()) { + if (Optional<llvm::APSInt> Result = + StepExpr->getIntegerConstantExpr(Context)) { + if (!Result->isNegative() && !Result->isStrictlyPositive()) + Diag(StepLoc, diag::warn_omp_linear_step_zero) + << Vars[0] << (Vars.size() > 1); + } else if (CalcStep.isUsable()) { // Calculate the step beforehand instead of doing this on each iteration. // (This is not used if the number of iterations may be kfold-ed). CalcStepExpr = CalcStep.get(); @@ -16645,11 +16952,14 @@ namespace { class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> { Sema &SemaRef; OpenMPClauseKind CKind = OMPC_unknown; + OpenMPDirectiveKind DKind = OMPD_unknown; OMPClauseMappableExprCommon::MappableExprComponentList &Components; + bool IsNonContiguous = false; bool NoDiagnose = false; const Expr *RelevantExpr = nullptr; bool AllowUnitySizeArraySection = true; bool AllowWholeSizeArraySection = true; + bool AllowAnotherPtr = true; SourceLocation ELoc; SourceRange ERange; @@ -16674,7 +16984,7 @@ public: assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); RelevantExpr = DRE; // Record the component. - Components.emplace_back(DRE, DRE->getDecl()); + Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous); return true; } @@ -16746,7 +17056,7 @@ public: AllowWholeSizeArraySection = false; // Record the component. - Components.emplace_back(ME, FD); + Components.emplace_back(ME, FD, IsNonContiguous); return RelevantExpr || Visit(E); } @@ -16784,7 +17094,7 @@ public: } // Record the component - we don't have any declaration associated. - Components.emplace_back(AE, nullptr); + Components.emplace_back(AE, nullptr, IsNonContiguous); return RelevantExpr || Visit(E); } @@ -16823,6 +17133,13 @@ public: // pointer. Otherwise, only unitary sections are accepted. if (NotWhole || IsPointer) AllowWholeSizeArraySection = false; + } else if (DKind == OMPD_target_update && + SemaRef.getLangOpts().OpenMP >= 50) { + if (IsPointer && !AllowAnotherPtr) + SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined) + << /*array of unknown bound */ 1; + else + IsNonContiguous = true; } else if (AllowUnitySizeArraySection && NotUnity) { // A unity or whole array section is not allowed and that is not // compatible with the properties of the current array section. @@ -16832,6 +17149,9 @@ public: return false; } + if (IsPointer) + AllowAnotherPtr = false; + if (const auto *TE = dyn_cast<CXXThisExpr>(E)) { Expr::EvalResult ResultR; Expr::EvalResult ResultL; @@ -16857,14 +17177,14 @@ public: } // Record the component - we don't have any declaration associated. - Components.emplace_back(OASE, nullptr); + Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false); return RelevantExpr || Visit(E); } bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) { Expr *Base = E->getBase(); // Record the component - we don't have any declaration associated. - Components.emplace_back(E, nullptr); + Components.emplace_back(E, nullptr, IsNonContiguous); return Visit(Base->IgnoreParenImpCasts()); } @@ -16877,7 +17197,7 @@ public: } if (!RelevantExpr) { // Record the component if haven't found base decl. - Components.emplace_back(UO, nullptr); + Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false); } return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts()); } @@ -16893,7 +17213,7 @@ public: // know the other subtree is just an offset) Expr *LE = BO->getLHS()->IgnoreParenImpCasts(); Expr *RE = BO->getRHS()->IgnoreParenImpCasts(); - Components.emplace_back(BO, nullptr); + Components.emplace_back(BO, nullptr, false); assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() || RE->getType().getTypePtr() == BO->getType().getTypePtr()) && "Either LHS or RHS have base decl inside"); @@ -16904,7 +17224,12 @@ public: bool VisitCXXThisExpr(CXXThisExpr *CTE) { assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); RelevantExpr = CTE; - Components.emplace_back(CTE, nullptr); + Components.emplace_back(CTE, nullptr, IsNonContiguous); + return true; + } + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) { + assert(!RelevantExpr && "RelevantExpr is expected to be nullptr"); + Components.emplace_back(COCE, nullptr, IsNonContiguous); return true; } bool VisitStmt(Stmt *) { @@ -16915,10 +17240,10 @@ public: return RelevantExpr; } explicit MapBaseChecker( - Sema &SemaRef, OpenMPClauseKind CKind, + Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, OMPClauseMappableExprCommon::MappableExprComponentList &Components, bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange) - : SemaRef(SemaRef), CKind(CKind), Components(Components), + : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components), NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {} }; } // namespace @@ -16930,13 +17255,30 @@ public: static const Expr *checkMapClauseExpressionBase( Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, - OpenMPClauseKind CKind, bool NoDiagnose) { + OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) { SourceLocation ELoc = E->getExprLoc(); SourceRange ERange = E->getSourceRange(); - MapBaseChecker Checker(SemaRef, CKind, CurComponents, NoDiagnose, ELoc, + MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc, ERange); - if (Checker.Visit(E->IgnoreParens())) + if (Checker.Visit(E->IgnoreParens())) { + // Check if the highest dimension array section has length specified + if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() && + (CKind == OMPC_to || CKind == OMPC_from)) { + auto CI = CurComponents.rbegin(); + auto CE = CurComponents.rend(); + for (; CI != CE; ++CI) { + const auto *OASE = + dyn_cast<OMPArraySectionExpr>(CI->getAssociatedExpression()); + if (!OASE) + continue; + if (OASE && OASE->getLength()) + break; + SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length) + << ERange; + } + } return Checker.getFoundBase(); + } return nullptr; } @@ -17347,6 +17689,7 @@ static void checkMappableExpressionList( auto &DeclNames = SemaRef.getASTContext().DeclarationNames; MapperId.setName(DeclNames.getIdentifier( &SemaRef.getASTContext().Idents.get("default"))); + MapperId.setLoc(StartLoc); } // Iterators to find the current unresolved mapper expression. @@ -17413,7 +17756,8 @@ static void checkMappableExpressionList( // Obtain the array or member expression bases if required. Also, fill the // components array with all the components identified in the process. const Expr *BE = checkMapClauseExpressionBase( - SemaRef, SimpleExpr, CurComponents, CKind, /*NoDiagnose=*/false); + SemaRef, SimpleExpr, CurComponents, CKind, DSAS->getCurrentDirective(), + /*NoDiagnose=*/false); if (!BE) continue; @@ -17478,6 +17822,7 @@ static void checkMappableExpressionList( /*CurrentRegionOnly=*/true, CurComponents, CKind)) break; if (CKind == OMPC_map && + (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) && checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr, /*CurrentRegionOnly=*/false, CurComponents, CKind)) break; @@ -17623,9 +17968,9 @@ OMPClause *Sema::ActOnOpenMPMapClause( OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { - OpenMPMapModifierKind Modifiers[] = {OMPC_MAP_MODIFIER_unknown, - OMPC_MAP_MODIFIER_unknown, - OMPC_MAP_MODIFIER_unknown}; + OpenMPMapModifierKind Modifiers[] = { + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers]; // Process map-type-modifiers, flag errors for duplicate modifiers. @@ -17944,10 +18289,10 @@ QualType Sema::ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, return MapperType; } -OMPDeclareMapperDecl *Sema::ActOnOpenMPDeclareMapperDirectiveStart( +Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareMapperDirective( Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, - Decl *PrevDeclInScope) { + Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) { LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPMapperName, forRedeclarationInCurContext()); // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions @@ -18007,48 +18352,51 @@ OMPDeclareMapperDecl *Sema::ActOnOpenMPDeclareMapperDirectiveStart( Invalid = true; } auto *DMD = OMPDeclareMapperDecl::Create(Context, DC, StartLoc, Name, - MapperType, VN, PrevDMD); - DC->addDecl(DMD); + MapperType, VN, Clauses, PrevDMD); + if (S) + PushOnScopeChains(DMD, S); + else + DC->addDecl(DMD); DMD->setAccess(AS); if (Invalid) DMD->setInvalidDecl(); - // Enter new function scope. - PushFunctionScope(); - setFunctionHasBranchProtectedScope(); - - CurContext = DMD; + auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl(); + VD->setDeclContext(DMD); + VD->setLexicalDeclContext(DMD); + DMD->addDecl(VD); + DMD->setMapperVarRef(MapperVarRef); - return DMD; + return DeclGroupPtrTy::make(DeclGroupRef(DMD)); } -void Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(OMPDeclareMapperDecl *DMD, - Scope *S, - QualType MapperType, - SourceLocation StartLoc, - DeclarationName VN) { - VarDecl *VD = buildVarDecl(*this, StartLoc, MapperType, VN.getAsString()); +ExprResult +Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, + SourceLocation StartLoc, + DeclarationName VN) { + TypeSourceInfo *TInfo = + Context.getTrivialTypeSourceInfo(MapperType, StartLoc); + auto *VD = VarDecl::Create(Context, Context.getTranslationUnitDecl(), + StartLoc, StartLoc, VN.getAsIdentifierInfo(), + MapperType, TInfo, SC_None); if (S) - PushOnScopeChains(VD, S); - else - DMD->addDecl(VD); - Expr *MapperVarRefExpr = buildDeclRefExpr(*this, VD, MapperType, StartLoc); - DMD->setMapperVarRef(MapperVarRefExpr); + PushOnScopeChains(VD, S, /*AddToContext=*/false); + Expr *E = buildDeclRefExpr(*this, VD, MapperType, StartLoc); + DSAStack->addDeclareMapperVarRef(E); + return E; } -Sema::DeclGroupPtrTy -Sema::ActOnOpenMPDeclareMapperDirectiveEnd(OMPDeclareMapperDecl *D, Scope *S, - ArrayRef<OMPClause *> ClauseList) { - PopDeclContext(); - PopFunctionScopeInfo(); - - if (D) { - if (S) - PushOnScopeChains(D, S, /*AddToContext=*/false); - D->CreateClauses(Context, ClauseList); - } +bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const { + assert(LangOpts.OpenMP && "Expected OpenMP mode."); + const Expr *Ref = DSAStack->getDeclareMapperVarRef(); + if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) + return VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl(); + return true; +} - return DeclGroupPtrTy::make(DeclGroupRef(D)); +const ValueDecl *Sema::getOpenMPDeclareMapperVarName() const { + assert(LangOpts.OpenMP && "Expected OpenMP mode."); + return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl(); } OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams, @@ -18273,9 +18621,9 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, Context)) { - if (Result.isSigned() && !Result.isStrictlyPositive()) { + if (Optional<llvm::APSInt> Result = + ValExpr->getIntegerConstantExpr(Context)) { + if (Result->isSigned() && !Result->isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) << "dist_schedule" << ChunkSize->getSourceRange(); return nullptr; @@ -18326,20 +18674,38 @@ OMPClause *Sema::ActOnOpenMPDefaultmapClause( bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) || (LangOpts.OpenMP >= 50 && KindLoc.isInvalid()); if (!isDefaultmapKind || !isDefaultmapModifier) { - std::string ModifierValue = "'alloc', 'from', 'to', 'tofrom', " + StringRef KindValue = "'scalar', 'aggregate', 'pointer'"; + if (LangOpts.OpenMP == 50) { + StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', " "'firstprivate', 'none', 'default'"; - std::string KindValue = "'scalar', 'aggregate', 'pointer'"; - if (!isDefaultmapKind && isDefaultmapModifier) { - Diag(KindLoc, diag::err_omp_unexpected_clause_value) - << KindValue << getOpenMPClauseName(OMPC_defaultmap); - } else if (isDefaultmapKind && !isDefaultmapModifier) { - Diag(MLoc, diag::err_omp_unexpected_clause_value) - << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + if (!isDefaultmapKind && isDefaultmapModifier) { + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << KindValue << getOpenMPClauseName(OMPC_defaultmap); + } else if (isDefaultmapKind && !isDefaultmapModifier) { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + } else { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << KindValue << getOpenMPClauseName(OMPC_defaultmap); + } } else { - Diag(MLoc, diag::err_omp_unexpected_clause_value) - << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); - Diag(KindLoc, diag::err_omp_unexpected_clause_value) - << KindValue << getOpenMPClauseName(OMPC_defaultmap); + StringRef ModifierValue = + "'alloc', 'from', 'to', 'tofrom', " + "'firstprivate', 'none', 'default', 'present'"; + if (!isDefaultmapKind && isDefaultmapModifier) { + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << KindValue << getOpenMPClauseName(OMPC_defaultmap); + } else if (isDefaultmapKind && !isDefaultmapModifier) { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + } else { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << ModifierValue << getOpenMPClauseName(OMPC_defaultmap); + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << KindValue << getOpenMPClauseName(OMPC_defaultmap); + } } return nullptr; } @@ -18377,14 +18743,14 @@ bool Sema::ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc) { Diag(Loc, diag::err_omp_region_not_file_context); return false; } - ++DeclareTargetNestingLevel; + DeclareTargetNesting.push_back(Loc); return true; } void Sema::ActOnFinishOpenMPDeclareTargetDirective() { - assert(DeclareTargetNestingLevel > 0 && + assert(!DeclareTargetNesting.empty() && "Unexpected ActOnFinishOpenMPDeclareTargetDirective"); - --DeclareTargetNestingLevel; + DeclareTargetNesting.pop_back(); } NamedDecl * @@ -18437,19 +18803,25 @@ void Sema::ActOnOpenMPDeclareTargetName( (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced())) Diag(Loc, diag::warn_omp_declare_target_after_first_use); + auto *VD = cast<ValueDecl>(ND); Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = - OMPDeclareTargetDeclAttr::getDeviceType(cast<ValueDecl>(ND)); - if (DevTy.hasValue() && *DevTy != DT) { + OMPDeclareTargetDeclAttr::getDeviceType(VD); + Optional<SourceLocation> AttrLoc = OMPDeclareTargetDeclAttr::getLocation(VD); + if (DevTy.hasValue() && *DevTy != DT && + (DeclareTargetNesting.empty() || + *AttrLoc != DeclareTargetNesting.back())) { Diag(Loc, diag::err_omp_device_type_mismatch) << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DT) << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(*DevTy); return; } Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(cast<ValueDecl>(ND)); - if (!Res) { - auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(Context, MT, DT, - SourceRange(Loc, Loc)); + OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); + if (!Res || (!DeclareTargetNesting.empty() && + *AttrLoc == DeclareTargetNesting.back())) { + auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( + Context, MT, DT, DeclareTargetNesting.size() + 1, + SourceRange(Loc, Loc)); ND->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(ND, A); @@ -18541,7 +18913,9 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, isa<FunctionTemplateDecl>(D)) { auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( Context, OMPDeclareTargetDeclAttr::MT_To, - OMPDeclareTargetDeclAttr::DT_Any, SourceRange(IdLoc, IdLoc)); + OMPDeclareTargetDeclAttr::DT_Any, DeclareTargetNesting.size(), + SourceRange(DeclareTargetNesting.back(), + DeclareTargetNesting.back())); D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(D, A); @@ -18554,11 +18928,31 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D); } -OMPClause *Sema::ActOnOpenMPToClause(ArrayRef<Expr *> VarList, - CXXScopeSpec &MapperIdScopeSpec, - DeclarationNameInfo &MapperId, - const OMPVarListLocTy &Locs, - ArrayRef<Expr *> UnresolvedMappers) { +OMPClause *Sema::ActOnOpenMPToClause( + ArrayRef<OpenMPMotionModifierKind> MotionModifiers, + ArrayRef<SourceLocation> MotionModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, + SourceLocation ColonLoc, ArrayRef<Expr *> VarList, + const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { + OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown, + OMPC_MOTION_MODIFIER_unknown}; + SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers]; + + // Process motion-modifiers, flag errors for duplicate modifiers. + unsigned Count = 0; + for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) { + if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown && + llvm::find(Modifiers, MotionModifiers[I]) != std::end(Modifiers)) { + Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier); + continue; + } + assert(Count < NumberOfOMPMotionModifiers && + "Modifiers exceed the allowed number of motion modifiers"); + Modifiers[Count] = MotionModifiers[I]; + ModifiersLoc[Count] = MotionModifiersLoc[I]; + ++Count; + } + MappableVarListInfo MVLI(VarList); checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, Locs.StartLoc, MapperIdScopeSpec, MapperId, UnresolvedMappers); @@ -18567,15 +18961,35 @@ OMPClause *Sema::ActOnOpenMPToClause(ArrayRef<Expr *> VarList, return OMPToClause::Create( Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, - MVLI.VarComponents, MVLI.UDMapperList, + MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId); } -OMPClause *Sema::ActOnOpenMPFromClause(ArrayRef<Expr *> VarList, - CXXScopeSpec &MapperIdScopeSpec, - DeclarationNameInfo &MapperId, - const OMPVarListLocTy &Locs, - ArrayRef<Expr *> UnresolvedMappers) { +OMPClause *Sema::ActOnOpenMPFromClause( + ArrayRef<OpenMPMotionModifierKind> MotionModifiers, + ArrayRef<SourceLocation> MotionModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, + SourceLocation ColonLoc, ArrayRef<Expr *> VarList, + const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) { + OpenMPMotionModifierKind Modifiers[] = {OMPC_MOTION_MODIFIER_unknown, + OMPC_MOTION_MODIFIER_unknown}; + SourceLocation ModifiersLoc[NumberOfOMPMotionModifiers]; + + // Process motion-modifiers, flag errors for duplicate modifiers. + unsigned Count = 0; + for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) { + if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown && + llvm::find(Modifiers, MotionModifiers[I]) != std::end(Modifiers)) { + Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier); + continue; + } + assert(Count < NumberOfOMPMotionModifiers && + "Modifiers exceed the allowed number of motion modifiers"); + Modifiers[Count] = MotionModifiers[I]; + ModifiersLoc[Count] = MotionModifiersLoc[I]; + ++Count; + } + MappableVarListInfo MVLI(VarList); checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, Locs.StartLoc, MapperIdScopeSpec, MapperId, UnresolvedMappers); @@ -18584,7 +18998,7 @@ OMPClause *Sema::ActOnOpenMPFromClause(ArrayRef<Expr *> VarList, return OMPFromClause::Create( Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, - MVLI.VarComponents, MVLI.UDMapperList, + MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId); } @@ -18661,8 +19075,8 @@ OMPClause *Sema::ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList, // only need a component. MVLI.VarBaseDeclarations.push_back(D); MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); - MVLI.VarComponents.back().push_back( - OMPClauseMappableExprCommon::MappableComponent(SimpleRefExpr, D)); + MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D, + /*IsNonContiguous=*/false); } if (MVLI.ProcessedVarList.empty()) @@ -18713,8 +19127,8 @@ OMPClause *Sema::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList, if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) || isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts()))) Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get(); - MVLI.VarComponents.back().push_back( - OMPClauseMappableExprCommon::MappableComponent(Component, D)); + MVLI.VarComponents.back().emplace_back(Component, D, + /*IsNonContiguous=*/false); } if (MVLI.ProcessedVarList.empty()) @@ -18780,7 +19194,8 @@ OMPClause *Sema::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList, // Store the components in the stack so that they can be used to check // against other clauses later on. - OMPClauseMappableExprCommon::MappableComponent MC(SimpleRefExpr, D); + OMPClauseMappableExprCommon::MappableComponent MC( + SimpleRefExpr, D, /*IsNonContiguous=*/false); DSAStack->addMappableExpressionComponents( D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr); @@ -19022,7 +19437,7 @@ OMPClause *Sema::ActOnOpenMPUsesAllocatorClause( [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) && !findOMPAlloctraitT(*this, StartLoc, DSAStack)) return nullptr; - llvm::SmallSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators; + llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators; for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); StringRef Allocator = |