diff options
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 1030 |
1 files changed, 858 insertions, 172 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index c7e0d2aee036..3fce0e27e9b3 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -23,13 +23,17 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/OpenMPKinds.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/PointerEmbeddedInt.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" using namespace clang; +using namespace llvm::omp; //===----------------------------------------------------------------------===// // Stack of data-sharing attributes for variables @@ -48,12 +52,6 @@ enum DefaultDataSharingAttributes { DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'. }; -/// Attributes of the defaultmap clause. -enum DefaultMapAttributes { - DMA_unspecified, /// Default mapping is not specified. - DMA_tofrom_scalar, /// Default mapping is 'tofrom:scalar'. -}; - /// Stack for tracking declarations used in OpenMP directives and /// clauses and their data-sharing attributes. class DSAStackTy { @@ -85,7 +83,7 @@ private: DeclRefExpr *PrivateCopy = nullptr; }; using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>; - using AlignedMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; + using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>; using LCDeclInfo = std::pair<unsigned, VarDecl *>; using LoopControlVariablesMapTy = llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>; @@ -115,17 +113,25 @@ private: }; using DeclReductionMapTy = llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>; + struct DefaultmapInfo { + OpenMPDefaultmapClauseModifier ImplicitBehavior = + OMPC_DEFAULTMAP_MODIFIER_unknown; + SourceLocation SLoc; + DefaultmapInfo() = default; + DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc) + : ImplicitBehavior(M), SLoc(Loc) {} + }; struct SharingMapTy { DeclSAMapTy SharingMap; DeclReductionMapTy ReductionMap; - AlignedMapTy AlignedMap; + UsedRefMapTy AlignedMap; + UsedRefMapTy NontemporalMap; MappedExprComponentsTy MappedExprComponents; LoopControlVariablesMapTy LCVMap; DefaultDataSharingAttributes DefaultAttr = DSA_unspecified; SourceLocation DefaultAttrLoc; - DefaultMapAttributes DefaultMapAttr = DMA_unspecified; - SourceLocation DefaultMapAttrLoc; + DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown]; OpenMPDirectiveKind Directive = OMPD_unknown; DeclarationNameInfo DirectiveName; Scope *CurScope = nullptr; @@ -416,6 +422,10 @@ public: /// add it and return NULL; otherwise return previous occurrence's expression /// for diagnostics. const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE); + /// If 'nontemporal' declaration for given variable \a D was not seen yet, + /// add it and return NULL; otherwise return previous occurrence's expression + /// for diagnostics. + const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE); /// Register specified variable as loop control variable. void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture); @@ -592,10 +602,18 @@ public: getTopOfStack().DefaultAttr = DSA_shared; getTopOfStack().DefaultAttrLoc = Loc; } - /// Set default data mapping attribute to 'tofrom:scalar'. - void setDefaultDMAToFromScalar(SourceLocation Loc) { - getTopOfStack().DefaultMapAttr = DMA_tofrom_scalar; - getTopOfStack().DefaultMapAttrLoc = Loc; + /// Set default data mapping attribute to Modifier:Kind + void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M, + OpenMPDefaultmapClauseKind Kind, + SourceLocation Loc) { + DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind]; + DMI.ImplicitBehavior = M; + DMI.SLoc = Loc; + } + /// Check whether the implicit-behavior has been set in defaultmap + bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) { + return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior != + OMPC_DEFAULTMAP_MODIFIER_unknown; } DefaultDataSharingAttributes getDefaultDSA() const { @@ -606,16 +624,53 @@ public: return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc; } - DefaultMapAttributes getDefaultDMA() const { - return isStackEmpty() ? DMA_unspecified - : getTopOfStack().DefaultMapAttr; + OpenMPDefaultmapClauseModifier + getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const { + return isStackEmpty() + ? OMPC_DEFAULTMAP_MODIFIER_unknown + : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior; + } + OpenMPDefaultmapClauseModifier + getDefaultmapModifierAtLevel(unsigned Level, + OpenMPDefaultmapClauseKind Kind) const { + return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior; + } + bool isDefaultmapCapturedByRef(unsigned Level, + OpenMPDefaultmapClauseKind Kind) const { + OpenMPDefaultmapClauseModifier M = + getDefaultmapModifierAtLevel(Level, Kind); + if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) { + return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) || + (M == OMPC_DEFAULTMAP_MODIFIER_to) || + (M == OMPC_DEFAULTMAP_MODIFIER_from) || + (M == OMPC_DEFAULTMAP_MODIFIER_tofrom); + } + return true; + } + static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M, + OpenMPDefaultmapClauseKind Kind) { + switch (Kind) { + case OMPC_DEFAULTMAP_scalar: + case OMPC_DEFAULTMAP_pointer: + return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) || + (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) || + (M == OMPC_DEFAULTMAP_MODIFIER_default); + case OMPC_DEFAULTMAP_aggregate: + return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate; + default: + break; + } + llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum"); } - DefaultMapAttributes getDefaultDMAAtLevel(unsigned Level) const { - return getStackElemAtLevel(Level).DefaultMapAttr; + bool mustBeFirstprivateAtLevel(unsigned Level, + OpenMPDefaultmapClauseKind Kind) const { + OpenMPDefaultmapClauseModifier M = + getDefaultmapModifierAtLevel(Level, Kind); + return mustBeFirstprivateBase(M, Kind); } - SourceLocation getDefaultDMALocation() const { - return isStackEmpty() ? SourceLocation() - : getTopOfStack().DefaultMapAttrLoc; + bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const { + OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind); + return mustBeFirstprivateBase(M, Kind); } /// Checks if the specified variable is a threadprivate. @@ -862,7 +917,7 @@ static const Expr *getExprAsWritten(const Expr *E) { E = FE->getSubExpr(); if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) - E = MTE->GetTemporaryExpr(); + E = MTE->getSubExpr(); while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E)) E = Binder->getSubExpr(); @@ -1023,6 +1078,21 @@ const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D, return It->second; } +const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D, + const Expr *NewDE) { + assert(!isStackEmpty() && "Data sharing attributes stack is empty"); + D = getCanonicalDecl(D); + SharingMapTy &StackElem = getTopOfStack(); + auto It = StackElem.NontemporalMap.find(D); + if (It == StackElem.NontemporalMap.end()) { + assert(NewDE && "Unexpected nullptr expr to be added into aligned map"); + StackElem.NontemporalMap[D] = NewDE; + return nullptr; + } + assert(It->second && "Unexpected nullptr expr in the aligned map"); + return It->second; +} + void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) { assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); D = getCanonicalDecl(D); @@ -1716,6 +1786,20 @@ void Sema::checkOpenMPDeviceExpr(const Expr *E) { << Context.getTargetInfo().getTriple().str() << E->getSourceRange(); } +static OpenMPDefaultmapClauseKind +getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD) { + if (LO.OpenMP <= 45) { + if (VD->getType().getNonReferenceType()->isScalarType()) + return OMPC_DEFAULTMAP_scalar; + return OMPC_DEFAULTMAP_aggregate; + } + if (VD->getType().getNonReferenceType()->isAnyPointerType()) + return OMPC_DEFAULTMAP_pointer; + if (VD->getType().getNonReferenceType()->isScalarType()) + return OMPC_DEFAULTMAP_scalar; + return OMPC_DEFAULTMAP_aggregate; +} + bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const { assert(LangOpts.OpenMP && "OpenMP is not allowed"); @@ -1834,11 +1918,13 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, } else { // 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->getDefaultDMAAtLevel(Level) == DMA_tofrom_scalar || + DSAStack->isDefaultmapCapturedByRef( + Level, getVariableCategoryFromDecl(LangOpts, D)) || DSAStack->hasExplicitDSA( D, [](OpenMPClauseKind K) { return K == OMPC_reduction; }, Level); } @@ -1894,6 +1980,11 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, assert(LangOpts.OpenMP && "OpenMP is not allowed"); D = getCanonicalDecl(D); + auto *VD = dyn_cast<VarDecl>(D); + // Do not capture constexpr variables. + if (VD && VD->isConstexpr()) + return nullptr; + // If we want to determine whether the variable should be captured from the // perspective of the current capturing scope, and we've already left all the // capturing scopes of the top directive on the stack, check from the @@ -1904,7 +1995,6 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo, // If we are attempting to capture a global variable in a directive with // 'target' we return true so that this global is also mapped to the device. // - auto *VD = dyn_cast<VarDecl>(D); if (VD && !VD->hasLocalStorage() && (getCurCapturedRegion() || getCurBlock() || getCurLambda())) { if (isInOpenMPDeclareTargetContext()) { @@ -2051,9 +2141,8 @@ void Sema::setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, NewLevel)) { OMPC = OMPC_map; - if (D->getType()->isScalarType() && - DSAStack->getDefaultDMAAtLevel(NewLevel) != - DefaultMapAttributes::DMA_tofrom_scalar) + if (DSAStack->mustBeFirstprivateAtLevel( + NewLevel, getVariableCategoryFromDecl(LangOpts, D))) OMPC = OMPC_firstprivate; break; } @@ -2141,6 +2230,11 @@ void Sema::EndOpenMPClause() { static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef<OMPClause *> Clauses); +static std::pair<ValueDecl *, bool> +getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, + SourceRange &ERange, bool AllowArraySection = false); +static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, + bool WithInit); void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { // OpenMP [2.14.3.5, Restrictions, C/C++, p.1] @@ -2185,6 +2279,31 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { } } Clause->setPrivateCopies(PrivateCopies); + continue; + } + // Finalize nontemporal clause by handling private copies, if any. + if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) { + SmallVector<Expr *, 8> PrivateRefs; + for (Expr *RefExpr : Clause->varlists()) { + assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); + SourceLocation ELoc; + SourceRange ERange; + Expr *SimpleRefExpr = RefExpr; + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); + if (Res.second) + // It will be analyzed later. + PrivateRefs.push_back(RefExpr); + ValueDecl *D = Res.first; + if (!D) + continue; + + const DSAStackTy::DSAVarData DVar = + DSAStack->getTopDSA(D, /*FromParent=*/false); + PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy + : SimpleRefExpr); + } + Clause->setPrivateRefs(PrivateRefs); + continue; } } // Check allocate clauses. @@ -2759,14 +2878,51 @@ static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, } } +static OpenMPMapClauseKind +getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, + bool IsAggregateOrDeclareTarget) { + OpenMPMapClauseKind Kind = OMPC_MAP_unknown; + switch (M) { + case OMPC_DEFAULTMAP_MODIFIER_alloc: + Kind = OMPC_MAP_alloc; + break; + case OMPC_DEFAULTMAP_MODIFIER_to: + Kind = OMPC_MAP_to; + break; + case OMPC_DEFAULTMAP_MODIFIER_from: + Kind = OMPC_MAP_from; + break; + case OMPC_DEFAULTMAP_MODIFIER_tofrom: + Kind = OMPC_MAP_tofrom; + break; + case OMPC_DEFAULTMAP_MODIFIER_firstprivate: + case OMPC_DEFAULTMAP_MODIFIER_last: + llvm_unreachable("Unexpected defaultmap implicit behavior"); + case OMPC_DEFAULTMAP_MODIFIER_none: + case OMPC_DEFAULTMAP_MODIFIER_default: + case OMPC_DEFAULTMAP_MODIFIER_unknown: + // IsAggregateOrDeclareTarget could be true if: + // 1. the implicit behavior for aggregate is tofrom + // 2. it's a declare target link + if (IsAggregateOrDeclareTarget) { + Kind = OMPC_MAP_tofrom; + break; + } + llvm_unreachable("Unexpected defaultmap implicit behavior"); + } + assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known"); + return Kind; +} + namespace { class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { DSAStackTy *Stack; Sema &SemaRef; bool ErrorFound = false; + bool TryCaptureCXXThisMembers = false; CapturedStmt *CS = nullptr; llvm::SmallVector<Expr *, 4> ImplicitFirstprivate; - llvm::SmallVector<Expr *, 4> ImplicitMap; + llvm::SmallVector<Expr *, 4> ImplicitMap[OMPC_MAP_delete]; Sema::VarsWithInheritedDSAType VarsWithInheritedDSA; llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations; @@ -2775,12 +2931,26 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> { if (!S->hasAssociatedStmt() || !S->getAssociatedStmt()) return; visitSubCaptures(S->getInnermostCapturedStmt()); + // Try to capture inner this->member references to generate correct mappings + // and diagnostics. + if (TryCaptureCXXThisMembers || + (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) && + llvm::any_of(S->getInnermostCapturedStmt()->captures(), + [](const CapturedStmt::Capture &C) { + return C.capturesThis(); + }))) { + bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers; + TryCaptureCXXThisMembers = true; + Visit(S->getInnermostCapturedStmt()->getCapturedStmt()); + TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers; + } } public: void VisitDeclRefExpr(DeclRefExpr *E) { - if (E->isTypeDependent() || E->isValueDependent() || - E->containsUnexpandedParameterPack() || E->isInstantiationDependent()) + if (TryCaptureCXXThisMembers || E->isTypeDependent() || + E->isValueDependent() || E->containsUnexpandedParameterPack() || + E->isInstantiationDependent()) return; if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) { // Check the datasharing rules for the expressions in the clauses. @@ -2825,6 +2995,39 @@ public: return; } + // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description] + // If implicit-behavior is none, each variable referenced in the + // construct that does not have a predetermined data-sharing attribute + // and does not appear in a to or link clause on a declare target + // directive must be listed in a data-mapping attribute clause, a + // data-haring attribute clause (including a data-sharing attribute + // clause on a combined construct where target. is one of the + // constituent constructs), or an is_device_ptr clause. + OpenMPDefaultmapClauseKind ClauseKind = + getVariableCategoryFromDecl(SemaRef.getLangOpts(), VD); + if (SemaRef.getLangOpts().OpenMP >= 50) { + bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) == + OMPC_DEFAULTMAP_MODIFIER_none; + if (DVar.CKind == OMPC_unknown && IsModifierNone && + VarsWithInheritedDSA.count(VD) == 0 && !Res) { + // Only check for data-mapping attribute and is_device_ptr here + // since we have already make sure that the declaration does not + // have a data-sharing attribute above + if (!Stack->checkMappableExprComponentListsForDecl( + VD, /*CurrentRegionOnly=*/true, + [VD](OMPClauseMappableExprCommon::MappableExprComponentListRef + MapExprComponents, + OpenMPClauseKind) { + auto MI = MapExprComponents.rbegin(); + auto ME = MapExprComponents.rend(); + return MI != ME && MI->getAssociatedDeclaration() == VD; + })) { + VarsWithInheritedDSA[VD] = E; + return; + } + } + } + if (isOpenMPTargetExecutionDirective(DKind) && !Stack->isLoopControlVariable(VD).first) { if (!Stack->checkMappableExprComponentListsForDecl( @@ -2854,13 +3057,16 @@ public: VD->getType().getNonReferenceType()->getAsCXXRecordDecl()) IsFirstprivate = RD->isLambda(); IsFirstprivate = - IsFirstprivate || - (VD->getType().getNonReferenceType()->isScalarType() && - Stack->getDefaultDMA() != DMA_tofrom_scalar && !Res); - if (IsFirstprivate) + IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res); + if (IsFirstprivate) { ImplicitFirstprivate.emplace_back(E); - else - ImplicitMap.emplace_back(E); + } else { + OpenMPDefaultmapClauseModifier M = + Stack->getDefaultmapModifier(ClauseKind); + OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( + M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res); + ImplicitMap[Kind].emplace_back(E); + } return; } } @@ -2939,7 +3145,11 @@ public: if (Stack->isClassPreviouslyMapped(TE->getType())) return; - ImplicitMap.emplace_back(E); + OpenMPDefaultmapClauseModifier Modifier = + Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate); + OpenMPMapClauseKind Kind = getMapClauseKindFromModifier( + Modifier, /*IsAggregateOrDeclareTarget*/ true); + ImplicitMap[Kind].emplace_back(E); return; } @@ -3014,7 +3224,7 @@ public: })) { Visit(E->getBase()); } - } else { + } else if (!TryCaptureCXXThisMembers) { Visit(E->getBase()); } } @@ -3068,7 +3278,9 @@ public: ArrayRef<Expr *> getImplicitFirstprivate() const { return ImplicitFirstprivate; } - ArrayRef<Expr *> getImplicitMap() const { return ImplicitMap; } + ArrayRef<Expr *> getImplicitMap(OpenMPDefaultmapClauseKind Kind) const { + return ImplicitMap[Kind]; + } const Sema::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const { return VarsWithInheritedDSA; } @@ -3090,6 +3302,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_parallel_sections: + case OMPD_parallel_master: case OMPD_teams: case OMPD_teams_distribute: case OMPD_teams_distribute_simd: { @@ -3282,7 +3495,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { AlwaysInlineAttr::Keyword_forceinline)); break; } - case OMPD_parallel_master_taskloop: { + case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: { QualType KmpInt32Ty = Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1) .withConst(); @@ -3779,7 +3993,10 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, ShouldBeInTargetRegion, ShouldBeInTeamsRegion } Recommend = NoRecommend; - if (isOpenMPSimdDirective(ParentRegion) && CurrentRegion != OMPD_ordered) { + if (isOpenMPSimdDirective(ParentRegion) && + ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) || + (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered && + CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic))) { // OpenMP [2.16, Nesting of Regions] // OpenMP constructs may not be nested inside a simd region. // OpenMP [2.8.1,simd Construct, Restrictions] @@ -3788,9 +4005,14 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, // Allowing a SIMD construct nested in another SIMD construct is an // extension. The OpenMP 4.5 spec does not allow it. Issue a warning // message. + // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions] + // The only OpenMP constructs that can be encountered during execution of + // a simd region are the atomic construct, the loop construct, the simd + // construct and the ordered construct with the simd clause. SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd) ? diag::err_omp_prohibited_region_simd - : diag::warn_omp_nesting_simd); + : diag::warn_omp_nesting_simd) + << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0); return CurrentRegion != OMPD_simd; } if (ParentRegion == OMPD_atomic) { @@ -3888,6 +4110,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || isOpenMPTaskingDirective(ParentRegion) || ParentRegion == OMPD_master || + ParentRegion == OMPD_parallel_master || ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered; } else if (isOpenMPWorksharingDirective(CurrentRegion) && @@ -3899,6 +4122,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) || isOpenMPTaskingDirective(ParentRegion) || ParentRegion == OMPD_master || + ParentRegion == OMPD_parallel_master || ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered; Recommend = ShouldBeInParallelRegion; @@ -3982,13 +4206,17 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, return false; } +struct Kind2Unsigned { + using argument_type = OpenMPDirectiveKind; + unsigned operator()(argument_type DK) { return unsigned(DK); } +}; static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef<OMPClause *> Clauses, ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) { bool ErrorFound = false; unsigned NamedModifiersNumber = 0; - SmallVector<const OMPIfClause *, OMPC_unknown + 1> FoundNameModifiers( - OMPD_unknown + 1); + llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers; + FoundNameModifiers.resize(unsigned(OMPD_unknown) + 1); SmallVector<SourceLocation, 4> NameModifierLoc; for (const OMPClause *C : Clauses) { if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) { @@ -4064,9 +4292,10 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, return ErrorFound; } -static std::pair<ValueDecl *, bool> -getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, - SourceRange &ERange, bool AllowArraySection = false) { +static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr, + SourceLocation &ELoc, + SourceRange &ERange, + bool AllowArraySection) { if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() || RefExpr->containsUnexpandedParameterPack()) return std::make_pair(nullptr, true); @@ -4271,8 +4500,12 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( SmallVector<Expr *, 4> ImplicitFirstprivates( DSAChecker.getImplicitFirstprivate().begin(), DSAChecker.getImplicitFirstprivate().end()); - SmallVector<Expr *, 4> ImplicitMaps(DSAChecker.getImplicitMap().begin(), - DSAChecker.getImplicitMap().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()); + } // Mark taskgroup task_reduction descriptors as implicitly firstprivate. for (OMPClause *C : Clauses) { if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) { @@ -4292,16 +4525,21 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( ErrorFound = true; } } - if (!ImplicitMaps.empty()) { + 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, - OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true, SourceLocation(), - SourceLocation(), ImplicitMaps, OMPVarListLocTy())) { + llvm::None, llvm::None, MapperIdScopeSpec, MapperId, Kind, + /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), + ImplicitMap, OMPVarListLocTy())) { ClausesWithImplicit.emplace_back(Implicit); ErrorFound |= - cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size(); + cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMap.size(); } else { ErrorFound = true; } @@ -4318,6 +4556,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_simd: Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_for: Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, @@ -4326,6 +4566,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_for_simd: Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_sections: Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, @@ -4358,6 +4600,13 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Res = ActOnOpenMPParallelForSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_parallel); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); + break; + case OMPD_parallel_master: + Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt, + StartLoc, EndLoc); + AllowedNameModifiers.push_back(OMPD_parallel); break; case OMPD_parallel_sections: Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt, @@ -4466,6 +4715,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_taskloop); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_master_taskloop: Res = ActOnOpenMPMasterTaskLoopDirective( @@ -4476,6 +4727,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Res = ActOnOpenMPMasterTaskLoopSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_taskloop); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_parallel_master_taskloop: Res = ActOnOpenMPParallelMasterTaskLoopDirective( @@ -4483,6 +4736,14 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( AllowedNameModifiers.push_back(OMPD_taskloop); AllowedNameModifiers.push_back(OMPD_parallel); break; + case OMPD_parallel_master_taskloop_simd: + Res = ActOnOpenMPParallelMasterTaskLoopSimdDirective( + ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + AllowedNameModifiers.push_back(OMPD_taskloop); + AllowedNameModifiers.push_back(OMPD_parallel); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); + break; case OMPD_distribute: Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); @@ -4501,21 +4762,29 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( Res = ActOnOpenMPDistributeParallelForSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_parallel); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_distribute_simd: Res = ActOnOpenMPDistributeSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_target_parallel_for_simd: Res = ActOnOpenMPTargetParallelForSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_target); AllowedNameModifiers.push_back(OMPD_parallel); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_target_simd: Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_target); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_teams_distribute: Res = ActOnOpenMPTeamsDistributeDirective( @@ -4524,11 +4793,15 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPD_teams_distribute_simd: Res = ActOnOpenMPTeamsDistributeSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_teams_distribute_parallel_for_simd: Res = ActOnOpenMPTeamsDistributeParallelForSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_parallel); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_teams_distribute_parallel_for: Res = ActOnOpenMPTeamsDistributeParallelForDirective( @@ -4556,11 +4829,15 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_target); AllowedNameModifiers.push_back(OMPD_parallel); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_target_teams_distribute_simd: Res = ActOnOpenMPTargetTeamsDistributeSimdDirective( ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA); AllowedNameModifiers.push_back(OMPD_target); + if (LangOpts.OpenMP >= 50) + AllowedNameModifiers.push_back(OMPD_simd); break; case OMPD_declare_target: case OMPD_end_declare_target: @@ -4586,13 +4863,17 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPC_num_threads: case OMPC_dist_schedule: // Do not analyse if no parent teams directive. - if (isOpenMPTeamsDirective(DSAStack->getCurrentDirective())) + if (isOpenMPTeamsDirective(Kind)) break; continue; case OMPC_if: - if (isOpenMPTeamsDirective(DSAStack->getCurrentDirective()) && + if (isOpenMPTeamsDirective(Kind) && cast<OMPIfClause>(C)->getNameModifier() != OMPD_target) break; + if (isOpenMPParallelDirective(Kind) && + isOpenMPTaskLoopDirective(Kind) && + cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel) + break; continue; case OMPC_schedule: break; @@ -4601,7 +4882,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPC_final: case OMPC_priority: // Do not analyze if no parent parallel directive. - if (isOpenMPParallelDirective(DSAStack->getCurrentDirective())) + if (isOpenMPParallelDirective(Kind)) break; continue; case OMPC_ordered: @@ -4644,6 +4925,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: + case OMPC_nontemporal: continue; case OMPC_allocator: case OMPC_flush: @@ -4671,9 +4953,17 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst())) continue; ErrorFound = true; - Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable) - << P.first << P.second->getSourceRange(); - Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none); + if (DSAStack->getDefaultDSA() == DSA_none) { + Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable) + << P.first << P.second->getSourceRange(); + Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none); + } else if (getLangOpts().OpenMP >= 50) { + Diag(P.second->getExprLoc(), + diag::err_omp_defaultmap_no_attr_for_variable) + << P.first << P.second->getSourceRange(); + Diag(DSAStack->getDefaultDSALocation(), + diag::note_omp_defaultmap_attr_none); + } } if (!AllowedNameModifiers.empty()) @@ -4781,8 +5071,9 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( // OpenMP [2.8.1, simd construct, Restrictions] // A list-item cannot appear in more than one aligned clause. if (AlignedArgs.count(CanonPVD) > 0) { - Diag(E->getExprLoc(), diag::err_omp_aligned_twice) - << 1 << E->getSourceRange(); + Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) + << 1 << getOpenMPClauseName(OMPC_aligned) + << E->getSourceRange(); Diag(AlignedArgs[CanonPVD]->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); @@ -4804,8 +5095,8 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( } if (isa<CXXThisExpr>(E)) { if (AlignedThis) { - Diag(E->getExprLoc(), diag::err_omp_aligned_twice) - << 2 << E->getSourceRange(); + Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) + << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange(); Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); } @@ -4950,6 +5241,29 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective( return DG; } +static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, + QualType NewType) { + assert(NewType->isFunctionProtoType() && + "Expected function type with prototype."); + assert(FD->getType()->isFunctionNoProtoType() && + "Expected function with type with no prototype."); + assert(FDWithProto->getType()->isFunctionProtoType() && + "Expected function with prototype."); + // Synthesize parameters with the same types. + FD->setType(NewType); + SmallVector<ParmVarDecl *, 16> Params; + for (const ParmVarDecl *P : FDWithProto->parameters()) { + auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(), + SourceLocation(), nullptr, P->getType(), + /*TInfo=*/nullptr, SC_None, nullptr); + Param->setScopeInfo(0, Params.size()); + Param->setImplicit(); + Params.push_back(Param); + } + + FD->setParams(Params); +} + Optional<std::pair<FunctionDecl *, Expr *>> Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, Expr *VariantRef, SourceRange SR) { @@ -5048,7 +5362,9 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, if (ICS.isFailure()) { Diag(VariantRef->getExprLoc(), diag::err_omp_declare_variant_incompat_types) - << VariantRef->getType() << FnPtrType << VariantRef->getSourceRange(); + << VariantRef->getType() + << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType()) + << VariantRef->getSourceRange(); return None; } VariantRefCast = PerformImplicitConversion( @@ -5088,6 +5404,24 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, return None; } + // Check if function types are compatible in C. + if (!LangOpts.CPlusPlus) { + QualType NewType = + Context.mergeFunctionTypes(FD->getType(), NewFD->getType()); + if (NewType.isNull()) { + Diag(VariantRef->getExprLoc(), + diag::err_omp_declare_variant_incompat_types) + << NewFD->getType() << FD->getType() << VariantRef->getSourceRange(); + return None; + } + if (NewType->isFunctionProtoType()) { + if (FD->getType()->isFunctionNoProtoType()) + setPrototype(*this, FD, NewFD, NewType); + else if (NewFD->getType()->isFunctionNoProtoType()) + setPrototype(*this, NewFD, FD, NewType); + } + } + // Check if variant function is not marked with declare variant directive. if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) { Diag(VariantRef->getExprLoc(), @@ -5148,10 +5482,9 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, // Check general compatibility. if (areMultiversionVariantFunctionsCompatible( - FD, NewFD, PDiag(diag::err_omp_declare_variant_noproto), - PartialDiagnosticAt( - SR.getBegin(), - PDiag(diag::note_omp_declare_variant_specified_here) << SR), + FD, NewFD, PartialDiagnostic::NullDiagnostic(), + PartialDiagnosticAt(SourceLocation(), + PartialDiagnostic::NullDiagnostic()), PartialDiagnosticAt( VariantRef->getExprLoc(), PDiag(diag::err_omp_declare_variant_doesnt_support)), @@ -5166,28 +5499,73 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, void Sema::ActOnOpenMPDeclareVariantDirective( FunctionDecl *FD, Expr *VariantRef, SourceRange SR, - const Sema::OpenMPDeclareVariantCtsSelectorData &Data) { - if (Data.CtxSet == OMPDeclareVariantAttr::CtxSetUnknown || - Data.Ctx == OMPDeclareVariantAttr::CtxUnknown) + ArrayRef<OMPCtxSelectorData> Data) { + if (Data.empty()) return; - Expr *Score = nullptr; - OMPDeclareVariantAttr::ScoreType ST = OMPDeclareVariantAttr::ScoreUnknown; - if (Data.CtxScore.isUsable()) { - ST = OMPDeclareVariantAttr::ScoreSpecified; - Score = Data.CtxScore.get(); - if (!Score->isTypeDependent() && !Score->isValueDependent() && - !Score->isInstantiationDependent() && - !Score->containsUnexpandedParameterPack()) { - llvm::APSInt Result; - ExprResult ICE = VerifyIntegerConstantExpression(Score, &Result); - if (ICE.isInvalid()) - return; + SmallVector<Expr *, 4> CtxScores; + SmallVector<unsigned, 4> CtxSets; + SmallVector<unsigned, 4> Ctxs; + SmallVector<StringRef, 4> ImplVendors, DeviceKinds; + bool IsError = false; + for (const OMPCtxSelectorData &D : Data) { + OpenMPContextSelectorSetKind CtxSet = D.CtxSet; + OpenMPContextSelectorKind Ctx = D.Ctx; + if (CtxSet == OMP_CTX_SET_unknown || Ctx == OMP_CTX_unknown) + return; + Expr *Score = nullptr; + if (D.Score.isUsable()) { + Score = D.Score.get(); + if (!Score->isTypeDependent() && !Score->isValueDependent() && + !Score->isInstantiationDependent() && + !Score->containsUnexpandedParameterPack()) { + Score = + PerformOpenMPImplicitIntegerConversion(Score->getExprLoc(), Score) + .get(); + if (Score) + Score = VerifyIntegerConstantExpression(Score).get(); + } + } else { + // OpenMP 5.0, 2.3.3 Matching and Scoring Context Selectors. + // The kind, arch, and isa selectors are given the values 2^l, 2^(l+1) and + // 2^(l+2), respectively, where l is the number of traits in the construct + // set. + // TODO: implement correct logic for isa and arch traits. + // TODO: take the construct context set into account when it is + // implemented. + int L = 0; // Currently set the number of traits in construct set to 0, + // since the construct trait set in not supported yet. + if (CtxSet == OMP_CTX_SET_device && Ctx == OMP_CTX_kind) + Score = ActOnIntegerConstant(SourceLocation(), std::pow(2, L)).get(); + else + Score = ActOnIntegerConstant(SourceLocation(), 0).get(); } + switch (Ctx) { + case OMP_CTX_vendor: + assert(CtxSet == OMP_CTX_SET_implementation && + "Expected implementation context selector set."); + ImplVendors.append(D.Names.begin(), D.Names.end()); + break; + case OMP_CTX_kind: + assert(CtxSet == OMP_CTX_SET_device && + "Expected device context selector set."); + DeviceKinds.append(D.Names.begin(), D.Names.end()); + break; + case OMP_CTX_unknown: + llvm_unreachable("Unknown context selector kind."); + } + IsError = IsError || !Score; + CtxSets.push_back(CtxSet); + Ctxs.push_back(Ctx); + CtxScores.push_back(Score); + } + if (!IsError) { + auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit( + Context, VariantRef, CtxScores.begin(), CtxScores.size(), + CtxSets.begin(), CtxSets.size(), Ctxs.begin(), Ctxs.size(), + ImplVendors.begin(), ImplVendors.size(), DeviceKinds.begin(), + DeviceKinds.size(), SR); + FD->addAttr(NewAttr); } - auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit( - Context, VariantRef, Score, Data.CtxSet, ST, Data.Ctx, - Data.ImplVendors.begin(), Data.ImplVendors.size(), SR); - FD->addAttr(NewAttr); } void Sema::markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc, @@ -5200,7 +5578,7 @@ void Sema::markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc, Func->specific_attrs<OMPDeclareVariantAttr>()) { // TODO: add checks for active OpenMP context where possible. Expr *VariantRef = A->getVariantFuncRef(); - auto *DRE = dyn_cast<DeclRefExpr>(VariantRef->IgnoreParenImpCasts()); + auto *DRE = cast<DeclRefExpr>(VariantRef->IgnoreParenImpCasts()); auto *F = cast<FunctionDecl>(DRE->getDecl()); if (!F->isDefined() && F->isTemplateInstantiation()) InstantiateFunctionDefinition(Loc, F->getFirstDecl()); @@ -6953,7 +7331,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, "Expected canonical for or range-based for loops."); CurStmt = cast<CXXForRangeStmt>(CurStmt)->getBody(); } - CurStmt = CurStmt->IgnoreContainers(); + CurStmt = OMPLoopDirective::tryToFindNextInnerLoop( + CurStmt, SemaRef.LangOpts.OpenMP >= 50); } for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) { if (checkOpenMPIterationSpace( @@ -6980,7 +7359,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, "Expected canonical for or range-based for loops."); CurStmt = cast<CXXForRangeStmt>(CurStmt)->getBody(); } - CurStmt = CurStmt->IgnoreContainers(); + CurStmt = OMPLoopDirective::tryToFindNextInnerLoop( + CurStmt, SemaRef.LangOpts.OpenMP >= 50); } Built.clear(/* size */ NestedLoopCount); @@ -7995,6 +8375,28 @@ StmtResult Sema::ActOnOpenMPParallelForSimdDirective( } StmtResult +Sema::ActOnOpenMPParallelMasterDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + 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. + // The point of exit cannot be a branch out of the structured block. + // longjmp() and throw() must not violate the entry/exit criteria. + CS->getCapturedDecl()->setNothrow(); + + setFunctionHasBranchProtectedScope(); + + return OMPParallelMasterDirective::Create(Context, StartLoc, EndLoc, Clauses, + AStmt); +} + +StmtResult Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) { @@ -8137,7 +8539,8 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, // OpenMP [2.8.1,simd Construct, Restrictions] // An ordered construct with the simd clause is the only OpenMP construct // that can appear in the simd region. - Diag(StartLoc, diag::err_omp_prohibited_region_simd); + Diag(StartLoc, diag::err_omp_prohibited_region_simd) + << (LangOpts.OpenMP >= 50 ? 1 : 0); ErrorFound = true; } else if (DependFound && (TC || SC)) { Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd) @@ -9467,6 +9870,74 @@ StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopDirective( Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); } +StmtResult Sema::ActOnOpenMPParallelMasterTaskLoopSimdDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { + if (!AStmt) + return StmtError(); + + assert(isa<CapturedStmt>(AStmt) && "Captured statement expected"); + 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. + // The point of exit cannot be a branch out of the structured block. + // longjmp() and throw() must not violate the entry/exit criteria. + CS->getCapturedDecl()->setNothrow(); + for (int ThisCaptureLevel = + getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd); + ThisCaptureLevel > 1; --ThisCaptureLevel) { + CS = cast<CapturedStmt>(CS->getCapturedStmt()); + // 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. + // The point of exit cannot be a branch out of the structured block. + // longjmp() and throw() must not violate the entry/exit criteria. + CS->getCapturedDecl()->setNothrow(); + } + + OMPLoopDirective::HelperExprs B; + // In presence of clause 'collapse' or 'ordered' with number of loops, it will + // define the nested loops number. + unsigned NestedLoopCount = checkOpenMPLoop( + OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses), + /*OrderedLoopCountExpr=*/nullptr, CS, *this, *DSAStack, + VarsWithImplicitDSA, B); + if (NestedLoopCount == 0) + return StmtError(); + + assert((CurContext->isDependentContext() || B.builtAll()) && + "omp for loop exprs were not built"); + + if (!CurContext->isDependentContext()) { + // Finalize the clauses that need pre-built expressions for CodeGen. + for (OMPClause *C : Clauses) { + if (auto *LC = dyn_cast<OMPLinearClause>(C)) + if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef), + B.NumIterations, *this, CurScope, + DSAStack)) + return StmtError(); + } + } + + // OpenMP, [2.9.2 taskloop Construct, Restrictions] + // The grainsize clause and num_tasks clause are mutually exclusive and may + // not appear on the same taskloop directive. + if (checkGrainsizeNumTasksClauses(*this, Clauses)) + return StmtError(); + // OpenMP, [2.9.2 taskloop Construct, Restrictions] + // If a reduction clause is present on the taskloop directive, the nogroup + // clause must not be specified. + if (checkReductionClauseWithNogroup(*this, Clauses)) + return StmtError(); + if (checkSimdlenSafelenSpecified(*this, Clauses)) + return StmtError(); + + setFunctionHasBranchProtectedScope(); + return OMPParallelMasterTaskLoopSimdDirective::Create( + Context, StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); +} + StmtResult Sema::ActOnOpenMPDistributeDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) { @@ -10317,6 +10788,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed."); } return Res; @@ -10328,29 +10800,47 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, // A return value of OMPD_unknown signifies that the expression should not // be captured. static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( - OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, + OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier = OMPD_unknown) { OpenMPDirectiveKind CaptureRegion = OMPD_unknown; switch (CKind) { case OMPC_if: switch (DKind) { + case OMPD_target_parallel_for_simd: + if (OpenMPVersion >= 50 && + (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) { + CaptureRegion = OMPD_parallel; + break; + } + LLVM_FALLTHROUGH; case OMPD_target_parallel: case OMPD_target_parallel_for: - case OMPD_target_parallel_for_simd: // If this clause applies to the nested 'parallel' region, capture within // the 'target' region, otherwise do not capture. if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel) CaptureRegion = OMPD_target; break; - case OMPD_target_teams_distribute_parallel_for: case OMPD_target_teams_distribute_parallel_for_simd: + if (OpenMPVersion >= 50 && + (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) { + CaptureRegion = OMPD_parallel; + break; + } + LLVM_FALLTHROUGH; + case OMPD_target_teams_distribute_parallel_for: // If this clause applies to the nested 'parallel' region, capture within // the 'teams' region, otherwise do not capture. if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel) CaptureRegion = OMPD_teams; break; - case OMPD_teams_distribute_parallel_for: case OMPD_teams_distribute_parallel_for_simd: + if (OpenMPVersion >= 50 && + (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) { + CaptureRegion = OMPD_parallel; + break; + } + LLVM_FALLTHROUGH; + case OMPD_teams_distribute_parallel_for: CaptureRegion = OMPD_teams; break; case OMPD_target_update: @@ -10362,24 +10852,63 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop) CaptureRegion = OMPD_parallel; break; + case OMPD_parallel_master_taskloop_simd: + if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) || + NameModifier == OMPD_taskloop) { + CaptureRegion = OMPD_parallel; + break; + } + if (OpenMPVersion <= 45) + break; + if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd) + CaptureRegion = OMPD_taskloop; + break; + case OMPD_parallel_for_simd: + if (OpenMPVersion <= 45) + break; + if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd) + CaptureRegion = OMPD_parallel; + break; + case OMPD_taskloop_simd: + case OMPD_master_taskloop_simd: + if (OpenMPVersion <= 45) + break; + if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd) + CaptureRegion = OMPD_taskloop; + break; + case OMPD_distribute_parallel_for_simd: + if (OpenMPVersion <= 45) + break; + if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd) + CaptureRegion = OMPD_parallel; + break; + case OMPD_target_simd: + if (OpenMPVersion >= 50 && + (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) + CaptureRegion = OMPD_target; + break; + case OMPD_teams_distribute_simd: + case OMPD_target_teams_distribute_simd: + if (OpenMPVersion >= 50 && + (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) + CaptureRegion = OMPD_teams; + break; case OMPD_cancel: case OMPD_parallel: + case OMPD_parallel_master: case OMPD_parallel_sections: case OMPD_parallel_for: - case OMPD_parallel_for_simd: case OMPD_target: - case OMPD_target_simd: case OMPD_target_teams: case OMPD_target_teams_distribute: - case OMPD_target_teams_distribute_simd: case OMPD_distribute_parallel_for: - case OMPD_distribute_parallel_for_simd: case OMPD_task: case OMPD_taskloop: - case OMPD_taskloop_simd: case OMPD_master_taskloop: - case OMPD_master_taskloop_simd: case OMPD_target_data: + case OMPD_simd: + case OMPD_for_simd: + case OMPD_distribute_simd: // Do not capture if-clause expressions. break; case OMPD_threadprivate: @@ -10396,9 +10925,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_declare_target: case OMPD_end_declare_target: case OMPD_teams: - case OMPD_simd: case OMPD_for: - case OMPD_for_simd: case OMPD_sections: case OMPD_section: case OMPD_single: @@ -10408,9 +10935,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_distribute: case OMPD_ordered: case OMPD_atomic: - case OMPD_distribute_simd: case OMPD_teams_distribute: - case OMPD_teams_distribute_simd: case OMPD_requires: llvm_unreachable("Unexpected OpenMP directive with if-clause"); case OMPD_unknown: @@ -10431,12 +10956,14 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( CaptureRegion = OMPD_teams; break; case OMPD_parallel: + case OMPD_parallel_master: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_distribute_parallel_for: case OMPD_distribute_parallel_for_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: // Do not capture num_threads-clause expressions. break; case OMPD_target_data: @@ -10513,12 +11040,14 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_master_taskloop: case OMPD_master_taskloop_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: case OMPD_target_data: case OMPD_target_enter_data: case OMPD_target_exit_data: case OMPD_target_update: case OMPD_cancel: case OMPD_parallel: + case OMPD_parallel_master: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: @@ -10583,12 +11112,14 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_master_taskloop: case OMPD_master_taskloop_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: case OMPD_target_data: case OMPD_target_enter_data: case OMPD_target_exit_data: case OMPD_target_update: case OMPD_cancel: case OMPD_parallel: + case OMPD_parallel_master: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: @@ -10653,6 +11184,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_master_taskloop: case OMPD_master_taskloop_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: case OMPD_target_data: case OMPD_target_enter_data: case OMPD_target_exit_data: @@ -10667,6 +11199,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_target_parallel: case OMPD_cancel: case OMPD_parallel: + case OMPD_parallel_master: case OMPD_parallel_sections: case OMPD_threadprivate: case OMPD_allocate: @@ -10727,6 +11260,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_master_taskloop: case OMPD_master_taskloop_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: case OMPD_target_data: case OMPD_target_enter_data: case OMPD_target_exit_data: @@ -10737,6 +11271,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_target_parallel: case OMPD_cancel: case OMPD_parallel: + case OMPD_parallel_master: case OMPD_parallel_sections: case OMPD_threadprivate: case OMPD_allocate: @@ -10802,8 +11337,10 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_master_taskloop: case OMPD_master_taskloop_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: case OMPD_cancel: case OMPD_parallel: + case OMPD_parallel_master: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: @@ -10851,6 +11388,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_master_taskloop_simd: break; case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: CaptureRegion = OMPD_parallel; break; case OMPD_target_update: @@ -10876,6 +11414,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_distribute_parallel_for_simd: case OMPD_cancel: case OMPD_parallel: + case OMPD_parallel_master: case OMPD_parallel_sections: case OMPD_parallel_for: case OMPD_parallel_for_simd: @@ -10960,6 +11499,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Unexpected OpenMP clause."); } return CaptureRegion; @@ -10984,8 +11524,8 @@ OMPClause *Sema::ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, ValExpr = Val.get(); OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); - CaptureRegion = - getOpenMPCaptureRegionForClause(DKind, OMPC_if, NameModifier); + CaptureRegion = getOpenMPCaptureRegionForClause( + DKind, OMPC_if, LangOpts.OpenMP, NameModifier); if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) { ValExpr = MakeFullExpr(ValExpr).get(); llvm::MapVector<const Expr *, DeclRefExpr *> Captures; @@ -11016,7 +11556,8 @@ OMPClause *Sema::ActOnOpenMPFinalClause(Expr *Condition, ValExpr = MakeFullExpr(Val.get()).get(); OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); - CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final); + CaptureRegion = + getOpenMPCaptureRegionForClause(DKind, OMPC_final, LangOpts.OpenMP); if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) { ValExpr = MakeFullExpr(ValExpr).get(); llvm::MapVector<const Expr *, DeclRefExpr *> Captures; @@ -11101,7 +11642,8 @@ isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, } if (!BuildCapture) return true; - *CaptureRegion = getOpenMPCaptureRegionForClause(DKind, CKind); + *CaptureRegion = + getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP); if (*CaptureRegion != OMPD_unknown && !SemaRef.CurContext->isDependentContext()) { ValExpr = SemaRef.MakeFullExpr(ValExpr).get(); @@ -11128,7 +11670,7 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads, OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); OpenMPDirectiveKind CaptureRegion = - getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads); + getOpenMPCaptureRegionForClause(DKind, OMPC_num_threads, LangOpts.OpenMP); if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) { ValExpr = MakeFullExpr(ValExpr).get(); llvm::MapVector<const Expr *, DeclRefExpr *> Captures; @@ -11315,9 +11857,8 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; case OMPC_proc_bind: - Res = ActOnOpenMPProcBindClause( - static_cast<OpenMPProcBindClauseKind>(Argument), ArgumentLoc, StartLoc, - LParenLoc, EndLoc); + Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument), + ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; case OMPC_atomic_default_mem_order: Res = ActOnOpenMPAtomicDefaultMemOrderClause( @@ -11381,6 +11922,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_dynamic_allocators: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed."); } return Res; @@ -11391,7 +11933,6 @@ getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef<unsigned> Exclude = llvm::None) { SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); - unsigned Bound = Last >= 2 ? Last - 2 : 0; unsigned Skipped = Exclude.size(); auto S = Exclude.begin(), E = Exclude.end(); for (unsigned I = First; I < Last; ++I) { @@ -11400,9 +11941,9 @@ getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, continue; } Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'"; - if (I == Bound - Skipped) + if (I + Skipped + 2 == Last) Out << " or "; - else if (I != Bound + 1 - Skipped) + else if (I + Skipped + 1 != Last) Out << ", "; } return Out.str(); @@ -11437,15 +11978,16 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind, OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); } -OMPClause *Sema::ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind, +OMPClause *Sema::ActOnOpenMPProcBindClause(ProcBindKind Kind, SourceLocation KindKwLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { - if (Kind == OMPC_PROC_BIND_unknown) { + if (Kind == OMP_PROC_BIND_unknown) { Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) - << getListOfPossibleValues(OMPC_proc_bind, /*First=*/0, - /*Last=*/OMPC_PROC_BIND_unknown) + << getListOfPossibleValues(OMPC_proc_bind, + /*First=*/unsigned(OMP_PROC_BIND_master), + /*Last=*/5) << getOpenMPClauseName(OMPC_proc_bind); return nullptr; } @@ -11561,6 +12103,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed."); } return Res; @@ -11659,8 +12202,8 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( return nullptr; } } else if (getOpenMPCaptureRegionForClause( - DSAStack->getCurrentDirective(), OMPC_schedule) != - OMPD_unknown && + DSAStack->getCurrentDirective(), OMPC_schedule, + LangOpts.OpenMP) != OMPD_unknown && !CurContext->isDependentContext()) { ValExpr = MakeFullExpr(ValExpr).get(); llvm::MapVector<const Expr *, DeclRefExpr *> Captures; @@ -11772,6 +12315,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_atomic_default_mem_order: case OMPC_device_type: case OMPC_match: + case OMPC_nontemporal: llvm_unreachable("Clause is not allowed."); } return Res; @@ -11857,11 +12401,10 @@ OMPClause *Sema::ActOnOpenMPVarListClause( OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr, const OMPVarListLocTy &Locs, SourceLocation ColonLoc, CXXScopeSpec &ReductionOrMapperIdScopeSpec, - DeclarationNameInfo &ReductionOrMapperId, OpenMPDependClauseKind DepKind, - OpenMPLinearClauseKind LinKind, + DeclarationNameInfo &ReductionOrMapperId, int ExtraModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, - ArrayRef<SourceLocation> MapTypeModifiersLoc, OpenMPMapClauseKind MapType, - bool IsMapTypeImplicit, SourceLocation DepLinMapLoc) { + ArrayRef<SourceLocation> MapTypeModifiersLoc, bool IsMapTypeImplicit, + SourceLocation DepLinMapLastLoc) { SourceLocation StartLoc = Locs.StartLoc; SourceLocation LParenLoc = Locs.LParenLoc; SourceLocation EndLoc = Locs.EndLoc; @@ -11874,7 +12417,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause( Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc); break; case OMPC_lastprivate: - Res = ActOnOpenMPLastprivateClause(VarList, StartLoc, LParenLoc, EndLoc); + assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown && + "Unexpected lastprivate modifier."); + Res = ActOnOpenMPLastprivateClause( + VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier), + DepLinMapLastLoc, ColonLoc, StartLoc, LParenLoc, EndLoc); break; case OMPC_shared: Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc); @@ -11895,8 +12442,12 @@ OMPClause *Sema::ActOnOpenMPVarListClause( ReductionOrMapperId); break; case OMPC_linear: - Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc, - LinKind, DepLinMapLoc, ColonLoc, EndLoc); + assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown && + "Unexpected linear modifier."); + Res = ActOnOpenMPLinearClause( + VarList, TailExpr, StartLoc, LParenLoc, + static_cast<OpenMPLinearClauseKind>(ExtraModifier), DepLinMapLastLoc, + ColonLoc, EndLoc); break; case OMPC_aligned: Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc, @@ -11912,14 +12463,19 @@ OMPClause *Sema::ActOnOpenMPVarListClause( Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc); break; case OMPC_depend: - Res = ActOnOpenMPDependClause(DepKind, DepLinMapLoc, ColonLoc, VarList, - StartLoc, LParenLoc, EndLoc); + assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown && + "Unexpected depend modifier."); + Res = ActOnOpenMPDependClause( + static_cast<OpenMPDependClauseKind>(ExtraModifier), DepLinMapLastLoc, + ColonLoc, VarList, StartLoc, LParenLoc, EndLoc); break; case OMPC_map: - Res = ActOnOpenMPMapClause(MapTypeModifiers, MapTypeModifiersLoc, - ReductionOrMapperIdScopeSpec, - ReductionOrMapperId, MapType, IsMapTypeImplicit, - DepLinMapLoc, ColonLoc, VarList, Locs); + assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown && + "Unexpected map modifier."); + Res = ActOnOpenMPMapClause( + MapTypeModifiers, MapTypeModifiersLoc, ReductionOrMapperIdScopeSpec, + ReductionOrMapperId, static_cast<OpenMPMapClauseKind>(ExtraModifier), + IsMapTypeImplicit, DepLinMapLastLoc, ColonLoc, VarList, Locs); break; case OMPC_to: Res = ActOnOpenMPToClause(VarList, ReductionOrMapperIdScopeSpec, @@ -11939,6 +12495,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause( Res = ActOnOpenMPAllocateClause(TailExpr, VarList, StartLoc, LParenLoc, ColonLoc, EndLoc); break; + case OMPC_nontemporal: + Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -12442,10 +13001,19 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, buildPreInits(Context, ExprCaptures)); } -OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { +OMPClause *Sema::ActOnOpenMPLastprivateClause( + ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind, + SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) { + if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) { + assert(ColonLoc.isValid() && "Colon location must be valid."); + Diag(LPKindLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0, + /*Last=*/OMPC_LASTPRIVATE_unknown) + << getOpenMPClauseName(OMPC_lastprivate); + return nullptr; + } + SmallVector<Expr *, 8> Vars; SmallVector<Expr *, 8> SrcExprs; SmallVector<Expr *, 8> DstExprs; @@ -12491,6 +13059,19 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, if (rejectConstNotMutableType(*this, D, Type, OMPC_lastprivate, ELoc)) continue; + // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions] + // A list item that appears in a lastprivate clause with the conditional + // modifier must be a scalar variable. + if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) { + Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar); + bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(D->getLocation(), + IsDecl ? diag::note_previous_decl : diag::note_defined_here) + << D; + continue; + } + OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] @@ -12599,6 +13180,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, return OMPLastprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs, AssignmentOps, + LPKind, LPKindLoc, ColonLoc, buildPreInits(Context, ExprCaptures), buildPostUpdate(*this, ExprPostUpdates)); } @@ -12916,7 +13498,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, } } if (ReductionIdScopeSpec.isSet()) { - SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier) << Range; + SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier) + << Ty << Range; return ExprError(); } return ExprEmpty(); @@ -13771,8 +14354,8 @@ bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, // A list item must be of integral or pointer type. Type = Type.getUnqualifiedType().getCanonicalType(); const auto *Ty = Type.getTypePtrOrNull(); - if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) && - !Ty->isPointerType())) { + if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() && + !Ty->isIntegralType(Context) && !Ty->isPointerType())) { Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type; if (D) { bool IsDecl = @@ -14066,7 +14649,8 @@ OMPClause *Sema::ActOnOpenMPAlignedClause( // OpenMP [2.8.1, simd construct, Restrictions] // A list-item cannot appear in more than one aligned clause. if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) { - Diag(ELoc, diag::err_omp_aligned_twice) << 0 << ERange; + Diag(ELoc, diag::err_omp_used_in_clause_twice) + << 0 << getOpenMPClauseName(OMPC_aligned) << ERange; Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); continue; @@ -14437,6 +15021,22 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, } OpsOffs.emplace_back(RHS, OOK); } else { + // OpenMP 5.0 [2.17.11, Restrictions] + // List items used in depend clauses cannot be zero-length array sections. + const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr); + if (OASE) { + const Expr *Length = OASE->getLength(); + Expr::EvalResult Result; + if (Length && !Length->isValueDependent() && + Length->EvaluateAsInt(Result, Context) && + Result.Val.getInt().isNullValue()) { + Diag(ELoc, + diag::err_omp_depend_zero_length_array_section_not_allowed) + << SimpleExpr->getSourceRange(); + continue; + } + } + auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (ASE && @@ -14496,7 +15096,7 @@ OMPClause *Sema::ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc, OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); OpenMPDirectiveKind CaptureRegion = - getOpenMPCaptureRegionForClause(DKind, OMPC_device); + getOpenMPCaptureRegionForClause(DKind, OMPC_device, LangOpts.OpenMP); if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) { ValExpr = MakeFullExpr(ValExpr).get(); llvm::MapVector<const Expr *, DeclRefExpr *> Captures; @@ -14517,7 +15117,7 @@ static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, return false; } if (FullCheck && !SemaRef.CurContext->isDependentContext() && - !QTy.isTrivialType(SemaRef.Context)) + !QTy.isTriviallyCopyableType(SemaRef.Context)) SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR; return true; } @@ -15408,8 +16008,22 @@ static void checkMappableExpressionList( return MC.getAssociatedDeclaration(); }); assert(I != CurComponents.end() && "Null decl on map clause."); - QualType Type = - I->getAssociatedDeclaration()->getType().getNonReferenceType(); + QualType Type; + auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens()); + auto *OASE = dyn_cast<OMPArraySectionExpr>(VE->IgnoreParens()); + if (ASE) { + Type = ASE->getType().getNonReferenceType(); + } else if (OASE) { + QualType BaseType = + OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); + if (const auto *ATy = BaseType->getAsArrayTypeUnsafe()) + Type = ATy->getElementType(); + else + Type = BaseType->getPointeeType(); + Type = Type.getNonReferenceType(); + } else { + Type = VE->getType(); + } // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4] // A list item in a to or from clause must have a mappable type. @@ -15419,6 +16033,8 @@ static void checkMappableExpressionList( DSAS, Type)) continue; + Type = I->getAssociatedDeclaration()->getType().getNonReferenceType(); + if (CKind == OMPC_map) { // target enter data // OpenMP [2.10.2, Restrictions, p. 99] @@ -15948,7 +16564,7 @@ OMPClause *Sema::ActOnOpenMPNumTeamsClause(Expr *NumTeams, OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); OpenMPDirectiveKind CaptureRegion = - getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams); + getOpenMPCaptureRegionForClause(DKind, OMPC_num_teams, LangOpts.OpenMP); if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) { ValExpr = MakeFullExpr(ValExpr).get(); llvm::MapVector<const Expr *, DeclRefExpr *> Captures; @@ -15974,8 +16590,8 @@ OMPClause *Sema::ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, return nullptr; OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); - OpenMPDirectiveKind CaptureRegion = - getOpenMPCaptureRegionForClause(DKind, OMPC_thread_limit); + OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( + DKind, OMPC_thread_limit, LangOpts.OpenMP); if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) { ValExpr = MakeFullExpr(ValExpr).get(); llvm::MapVector<const Expr *, DeclRefExpr *> Captures; @@ -16100,8 +16716,8 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( return nullptr; } } else if (getOpenMPCaptureRegionForClause( - DSAStack->getCurrentDirective(), OMPC_dist_schedule) != - OMPD_unknown && + DSAStack->getCurrentDirective(), OMPC_dist_schedule, + LangOpts.OpenMP) != OMPD_unknown && !CurContext->isDependentContext()) { ValExpr = MakeFullExpr(ValExpr).get(); llvm::MapVector<const Expr *, DeclRefExpr *> Captures; @@ -16120,26 +16736,57 @@ OMPClause *Sema::ActOnOpenMPDefaultmapClause( OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc) { - // OpenMP 4.5 only supports 'defaultmap(tofrom: scalar)' - if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom || Kind != OMPC_DEFAULTMAP_scalar) { - std::string Value; - SourceLocation Loc; - Value += "'"; - if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) { - Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap, - OMPC_DEFAULTMAP_MODIFIER_tofrom); - Loc = MLoc; - } else { - Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap, - OMPC_DEFAULTMAP_scalar); - Loc = KindLoc; + if (getLangOpts().OpenMP < 50) { + if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom || + Kind != OMPC_DEFAULTMAP_scalar) { + std::string Value; + SourceLocation Loc; + Value += "'"; + if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) { + Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap, + OMPC_DEFAULTMAP_MODIFIER_tofrom); + Loc = MLoc; + } else { + Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap, + OMPC_DEFAULTMAP_scalar); + Loc = KindLoc; + } + Value += "'"; + Diag(Loc, diag::err_omp_unexpected_clause_value) + << Value << getOpenMPClauseName(OMPC_defaultmap); + return nullptr; + } + } else { + bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown); + bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown); + if (!isDefaultmapKind || !isDefaultmapModifier) { + std::string 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); + } 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; + } + + // OpenMP [5.0, 2.12.5, Restrictions, p. 174] + // At most one defaultmap clause for each category can appear on the + // directive. + if (DSAStack->checkDefaultmapCategory(Kind)) { + Diag(StartLoc, diag::err_omp_one_defaultmap_each_category); + return nullptr; } - Value += "'"; - Diag(Loc, diag::err_omp_unexpected_clause_value) - << Value << getOpenMPClauseName(OMPC_defaultmap); - return nullptr; } - DSAStack->setDefaultDMAToFromScalar(StartLoc); + DSAStack->setDefaultDMAAttr(M, Kind, StartLoc); return new (Context) OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M); @@ -16604,3 +17251,42 @@ OMPClause *Sema::ActOnOpenMPAllocateClause( return OMPAllocateClause::Create(Context, StartLoc, LParenLoc, Allocator, ColonLoc, EndLoc, Vars); } + +OMPClause *Sema::ActOnOpenMPNontemporalClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + SmallVector<Expr *, 8> Vars; + for (Expr *RefExpr : VarList) { + assert(RefExpr && "NULL expr in OpenMP nontemporal clause."); + SourceLocation ELoc; + SourceRange ERange; + Expr *SimpleRefExpr = RefExpr; + auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange); + if (Res.second) + // It will be analyzed later. + Vars.push_back(RefExpr); + ValueDecl *D = Res.first; + if (!D) + continue; + + // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions. + // A list-item cannot appear in more than one nontemporal clause. + if (const Expr *PrevRef = + DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) { + Diag(ELoc, diag::err_omp_used_in_clause_twice) + << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange; + Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa) + << getOpenMPClauseName(OMPC_nontemporal); + continue; + } + + Vars.push_back(RefExpr); + } + + if (Vars.empty()) + return nullptr; + + return OMPNontemporalClause::Create(Context, StartLoc, LParenLoc, EndLoc, + Vars); +} |