diff options
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 919 |
1 files changed, 645 insertions, 274 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index dc1470bf7a9d..c767341d922b 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -39,6 +39,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Frontend/OpenMP/OMPAssume.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" +#include <optional> #include <set> using namespace clang; @@ -172,7 +173,8 @@ private: /// First argument (Expr *) contains optional argument of the /// 'ordered' clause, the second one is true if the regions has 'ordered' /// clause, false otherwise. - llvm::Optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion; + std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion; + bool RegionHasOrderConcurrent = false; unsigned AssociatedLoops = 1; bool HasMutipleLoops = false; const Decl *PossiblyLoopCounter = nullptr; @@ -213,6 +215,7 @@ private: llvm::SmallVector<ImplicitDefaultFDInfoTy, 8> ImplicitDefaultFirstprivateFDs; Expr *DeclareMapperVar = nullptr; + SmallVector<VarDecl *, 16> IteratorVarDecls; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) : Directive(DKind), DirectiveName(Name), CurScope(CurScope), @@ -847,7 +850,7 @@ public: std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const { if (const SharingMapTy *Top = getTopOfStackOrNull()) if (Top->OrderedRegion) - return Top->OrderedRegion.value(); + return *Top->OrderedRegion; return std::make_pair(nullptr, nullptr); } /// Returns true, if parent region is ordered (has associated @@ -862,9 +865,20 @@ public: getParentOrderedRegionParam() const { if (const SharingMapTy *Parent = getSecondOnStackOrNull()) if (Parent->OrderedRegion) - return Parent->OrderedRegion.value(); + return *Parent->OrderedRegion; return std::make_pair(nullptr, nullptr); } + /// Marks current region as having an 'order' clause. + void setRegionHasOrderConcurrent(bool HasOrderConcurrent) { + getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent; + } + /// Returns true, if parent region is order (has associated + /// 'order' clause), false - otherwise. + bool isParentOrderConcurrent() const { + if (const SharingMapTy *Parent = getSecondOnStackOrNull()) + return Parent->RegionHasOrderConcurrent; + return false; + } /// Marks current region as nowait (it has a 'nowait' clause). void setNowaitRegion(bool IsNowait = true) { getTopOfStack().NowaitRegion = IsNowait; @@ -1114,19 +1128,20 @@ public: } /// Checks if specified decl is used in uses allocator clause as the /// allocator. - Optional<UsesAllocatorsDeclKind> isUsesAllocatorsDecl(unsigned Level, - const Decl *D) const { + std::optional<UsesAllocatorsDeclKind> + isUsesAllocatorsDecl(unsigned Level, const Decl *D) const { const SharingMapTy &StackElem = getTopOfStack(); auto I = StackElem.UsesAllocatorsDecls.find(D); if (I == StackElem.UsesAllocatorsDecls.end()) - return None; + return std::nullopt; return I->getSecond(); } - Optional<UsesAllocatorsDeclKind> isUsesAllocatorsDecl(const Decl *D) const { + std::optional<UsesAllocatorsDeclKind> + isUsesAllocatorsDecl(const Decl *D) const { const SharingMapTy &StackElem = getTopOfStack(); auto I = StackElem.UsesAllocatorsDecls.find(D); if (I == StackElem.UsesAllocatorsDecls.end()) - return None; + return std::nullopt; return I->getSecond(); } @@ -1138,6 +1153,22 @@ public: const SharingMapTy *Top = getTopOfStackOrNull(); return Top ? Top->DeclareMapperVar : nullptr; } + + /// Add a new iterator variable. + void addIteratorVarDecl(VarDecl *VD) { + SharingMapTy &StackElem = getTopOfStack(); + StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl()); + } + /// Check if variable declaration is an iterator VarDecl. + bool isIteratorVarDecl(const VarDecl *VD) const { + const SharingMapTy *Top = getTopOfStackOrNull(); + if (!Top) + return false; + + return llvm::any_of(Top->IteratorVarDecls, [VD](const VarDecl *IteratorVD) { + return IteratorVD == VD->getCanonicalDecl(); + }); + } /// get captured field from ImplicitDefaultFirstprivateFDs VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const { const_iterator I = begin(); @@ -2093,7 +2124,7 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, // // ========================================================================= // | type | defaultmap | pvt | first | is_device_ptr | map | res. | - // | |(tofrom:scalar)| | pvt | | | | + // | |(tofrom:scalar)| | pvt | |has_dv_adr| | // ========================================================================= // | scl | | | | - | | bycopy| // | scl | | - | x | - | - | bycopy| @@ -2154,10 +2185,11 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, D](OMPClauseMappableExprCommon::MappableExprComponentListRef MapExprComponents, OpenMPClauseKind WhereFoundClauseKind) { - // Only the map clause information influences how a variable is - // captured. E.g. is_device_ptr does not require changing the default - // behavior. - if (WhereFoundClauseKind != OMPC_map) + // Both map and has_device_addr clauses information influences how a + // variable is captured. E.g. is_device_ptr does not require changing + // the default behavior. + if (WhereFoundClauseKind != OMPC_map && + WhereFoundClauseKind != OMPC_has_device_addr) return false; auto EI = MapExprComponents.rbegin(); @@ -2270,6 +2302,9 @@ bool Sema::isInOpenMPTargetExecutionDirective() const { } bool Sema::isOpenMPRebuildMemberExpr(ValueDecl *D) { + // Only rebuild for Field. + if (!dyn_cast<FieldDecl>(D)) + return false; DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA( D, [](OpenMPClauseKind C, bool AppliedToPointee, @@ -2661,7 +2696,7 @@ void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc) { assert(LangOpts.OpenMP && "Expected OpenMP compilation mode."); - Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = + std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl()); // Ignore host functions during device analyzis. if (LangOpts.OpenMPIsDevice && @@ -2686,6 +2721,24 @@ void Sema::finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, } if (!LangOpts.OpenMPIsDevice && !LangOpts.OpenMPOffloadMandatory && DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) { + // In OpenMP 5.2 or later, if the function has a host variant then allow + // that to be called instead + auto &&HasHostAttr = [](const FunctionDecl *Callee) { + for (OMPDeclareVariantAttr *A : + Callee->specific_attrs<OMPDeclareVariantAttr>()) { + auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef()); + auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl()); + std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = + OMPDeclareTargetDeclAttr::getDeviceType( + VariantFD->getMostRecentDecl()); + if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host) + return true; + } + return false; + }; + if (getLangOpts().OpenMP >= 52 && + Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee)) + return; // Diagnose nohost function called during host codegen. StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName( OMPC_device_type, OMPC_DEVICE_TYPE_nohost); @@ -2715,7 +2768,8 @@ void Sema::EndOpenMPClause() { static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, - SourceRange &ERange, bool AllowArraySection = false); + SourceRange &ERange, bool AllowArraySection = false, + StringRef DiagType = ""); /// Check consistency of the reduction clauses. static void checkReductionClauses(Sema &S, DSAStackTy *Stack, @@ -3226,13 +3280,15 @@ getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) { Allocator->containsUnexpandedParameterPack()) return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; + llvm::FoldingSetNodeID AEId; const Expr *AE = Allocator->IgnoreParenImpCasts(); + AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true); for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); const Expr *DefAllocator = Stack->getAllocator(AllocatorKind); - llvm::FoldingSetNodeID AEId, DAEId; - AE->Profile(AEId, S.getASTContext(), /*Canonical=*/true); - DefAllocator->Profile(DAEId, S.getASTContext(), /*Canonical=*/true); + llvm::FoldingSetNodeID DAEId; + DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(), + /*Canonical=*/true); if (AEId == DAEId) { AllocatorKindRes = AllocatorKind; break; @@ -3694,7 +3750,7 @@ public: return; // Skip internally declared static variables. - llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) && (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() || @@ -3764,9 +3820,8 @@ public: bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) == OMPC_DEFAULTMAP_MODIFIER_present; if (IsModifierPresent) { - if (llvm::find(ImplicitMapModifier[ClauseKind], - OMPC_MAP_MODIFIER_present) == - std::end(ImplicitMapModifier[ClauseKind])) { + if (!llvm::is_contained(ImplicitMapModifier[ClauseKind], + OMPC_MAP_MODIFIER_present)) { ImplicitMapModifier[ClauseKind].push_back( OMPC_MAP_MODIFIER_present); } @@ -3785,9 +3840,8 @@ public: // Variable is used if it has been marked as an array, array // section, array shaping or the variable iself. return StackComponents.size() == 1 || - std::all_of( - std::next(StackComponents.rbegin()), - StackComponents.rend(), + llvm::all_of( + llvm::drop_begin(llvm::reverse(StackComponents)), [](const OMPClauseMappableExprCommon:: MappableComponent &MC) { return MC.getAssociatedDeclaration() == @@ -4032,9 +4086,13 @@ public: Visit(C); } } - if (Expr *Callee = S->getCallee()) - if (auto *CE = dyn_cast<MemberExpr>(Callee->IgnoreParenImpCasts())) + if (Expr *Callee = S->getCallee()) { + auto *CI = Callee->IgnoreParenImpCasts(); + if (auto *CE = dyn_cast<MemberExpr>(CI)) Visit(CE->getBase()); + else if (auto *CE = dyn_cast<DeclRefExpr>(CI)) + Visit(CE); + } } void VisitStmt(Stmt *S) { for (Stmt *C : S->children()) { @@ -4529,6 +4587,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -4674,12 +4733,12 @@ void Sema::tryCaptureOpenMPLambdas(ValueDecl *V) { DSAStack->setForceCaptureByReferenceInTargetExecutable( /*V=*/true); if (RD->isLambda()) { - llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; + llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures; FieldDecl *ThisCapture; RD->getCaptureFields(Captures, ThisCapture); for (const LambdaCapture &LC : RD->captures()) { if (LC.getCaptureKind() == LCK_ByRef) { - VarDecl *VD = LC.getCapturedVar(); + VarDecl *VD = cast<VarDecl>(LC.getCapturedVar()); DeclContext *VDC = VD->getDeclContext(); if (!VDC->Encloses(CurContext)) continue; @@ -4939,6 +4998,14 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, ShouldBeInTeamsRegion, ShouldBeInLoopSimdRegion, } Recommend = NoRecommend; + if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() && + CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop && + CurrentRegion != OMPD_parallel && + !isOpenMPCombinedParallelADirective(CurrentRegion)) { + SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order) + << getOpenMPDirectiveName(CurrentRegion); + return true; + } if (isOpenMPSimdDirective(ParentRegion) && ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) || (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered && @@ -5277,7 +5344,8 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, - bool AllowArraySection) { + bool AllowArraySection, + StringRef DiagType) { if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() || RefExpr->containsUnexpandedParameterPack()) return std::make_pair(nullptr, true); @@ -5322,6 +5390,12 @@ static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr, if (IsArrayExpr != NoArrayExpr) { S.Diag(ELoc, diag::err_omp_expected_base_var_name) << IsArrayExpr << ERange; + } else if (!DiagType.empty()) { + unsigned DiagSelect = S.getLangOpts().CPlusPlus + ? (S.getCurrentThisType().isNull() ? 1 : 2) + : 0; + S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type) + << DiagSelect << DiagType << ERange; } else { S.Diag(ELoc, AllowArraySection @@ -6021,7 +6095,7 @@ processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, CXXScopeSpec MapperIdScopeSpec; DeclarationNameInfo MapperId; if (OMPClause *NewClause = S.ActOnOpenMPMapClause( - C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), + nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(), MapperIdScopeSpec, MapperId, C->getMapType(), /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SubExprs, OMPVarListLocTy())) @@ -6163,8 +6237,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( CXXScopeSpec MapperIdScopeSpec; DeclarationNameInfo MapperId; if (OMPClause *Implicit = ActOnOpenMPMapClause( - OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec, - MapperId, OMPC_MAP_tofrom, + nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), + MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true)) ClausesWithImplicit.emplace_back(Implicit); @@ -6180,7 +6254,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( DeclarationNameInfo MapperId; auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt); if (OMPClause *Implicit = ActOnOpenMPMapClause( - ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I], + nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I], MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), ImplicitMap, OMPVarListLocTy())) { @@ -6295,6 +6369,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( "No associated statement allowed for 'omp taskyield' directive"); Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc); break; + case OMPD_error: + assert(AStmt == nullptr && + "No associated statement allowed for 'omp error' directive"); + Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc); + break; case OMPD_barrier: assert(ClausesWithImplicit.empty() && "No clauses are allowed for 'omp barrier' directive"); @@ -6703,6 +6782,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPC_device_type: case OMPC_match: case OMPC_when: + case OMPC_at: + case OMPC_severity: + case OMPC_message: default: llvm_unreachable("Unexpected clause"); } @@ -7176,6 +7258,13 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, if (!CalleeFnDecl) return Call; + if (LangOpts.OpenMP >= 51 && CalleeFnDecl->getIdentifier() && + CalleeFnDecl->getName().startswith_insensitive("omp_")) { + // checking for any calls inside an Order region + if (Scope && Scope->isOpenMPOrderClauseScope()) + Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api); + } + if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>()) return Call; @@ -7268,20 +7357,20 @@ ExprResult Sema::ActOnOpenMPCall(ExprResult Call, Scope *Scope, return PseudoObjectExpr::Create(Context, CE, {NewCall.get()}, 0); } -Optional<std::pair<FunctionDecl *, Expr *>> +std::optional<std::pair<FunctionDecl *, Expr *>> Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR) { if (!DG || DG.get().isNull()) - return None; + return std::nullopt; const int VariantId = 1; // Must be applied only to single decl. if (!DG.get().isSingleDecl()) { Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant) << VariantId << SR; - return None; + return std::nullopt; } Decl *ADecl = DG.get().getSingleDecl(); if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl)) @@ -7292,7 +7381,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, if (!FD) { Diag(ADecl->getLocation(), diag::err_omp_function_expected) << VariantId << SR; - return None; + return std::nullopt; } auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) { @@ -7304,7 +7393,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, if (HasMultiVersionAttributes(FD)) { Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes) << SR; - return None; + return std::nullopt; } // Allow #pragma omp declare variant only if the function is not used. @@ -7322,7 +7411,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, // The VariantRef must point to function. if (!VariantRef) { Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId; - return None; + return std::nullopt; } auto ShouldDelayChecks = [](Expr *&E, bool) { @@ -7357,7 +7446,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, return true; }; if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions)) - return None; + return std::nullopt; QualType AdjustedFnType = FD->getType(); if (NumAppendArgs) { @@ -7365,7 +7454,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, if (!PTy) { Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required) << SR; - return None; + return std::nullopt; } // Adjust the function type to account for an extra omp_interop_t for each // specified in the append_args clause. @@ -7378,12 +7467,12 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, } if (!TD) { Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR; - return None; + return std::nullopt; } QualType InteropType = Context.getTypeDeclType(TD); if (PTy->isVariadic()) { Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR; - return None; + return std::nullopt; } llvm::SmallVector<QualType, 8> Params; Params.append(PTy->param_type_begin(), PTy->param_type_end()); @@ -7413,7 +7502,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, if (!ER.isUsable()) { Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) << VariantId << VariantRef->getSourceRange(); - return None; + return std::nullopt; } VariantRef = ER.get(); } else { @@ -7433,12 +7522,12 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, << VariantRef->getType() << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType()) << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange(); - return None; + return std::nullopt; } VariantRefCast = PerformImplicitConversion( VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting); if (!VariantRefCast.isUsable()) - return None; + return std::nullopt; } // Drop previously built artificial addr_of unary op for member functions. if (Method && !Method->isStatic()) { @@ -7454,7 +7543,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) { Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) << VariantId << VariantRef->getSourceRange(); - return None; + return std::nullopt; } // The VariantRef must point to function. @@ -7462,20 +7551,20 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, if (!DRE) { Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) << VariantId << VariantRef->getSourceRange(); - return None; + return std::nullopt; } auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl()); if (!NewFD) { Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected) << VariantId << VariantRef->getSourceRange(); - return None; + return std::nullopt; } if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) { Diag(VariantRef->getExprLoc(), diag::err_omp_declare_variant_same_base_function) << VariantRef->getSourceRange(); - return None; + return std::nullopt; } // Check if function types are compatible in C. @@ -7487,7 +7576,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, diag::err_omp_declare_variant_incompat_types) << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange(); - return None; + return std::nullopt; } if (NewType->isFunctionProtoType()) { if (FD->getType()->isFunctionNoProtoType()) @@ -7505,7 +7594,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, SourceRange SR = NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange(); Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR; - return None; + return std::nullopt; } enum DoesntSupport { @@ -7521,38 +7610,38 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, if (CXXFD->isVirtual()) { Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) << VirtFuncs; - return None; + return std::nullopt; } if (isa<CXXConstructorDecl>(FD)) { Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) << Constructors; - return None; + return std::nullopt; } if (isa<CXXDestructorDecl>(FD)) { Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) << Destructors; - return None; + return std::nullopt; } } if (FD->isDeleted()) { Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) << DeletedFuncs; - return None; + return std::nullopt; } if (FD->isDefaulted()) { Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) << DefaultedFuncs; - return None; + return std::nullopt; } if (FD->isConstexpr()) { Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support) << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs); - return None; + return std::nullopt; } // Check general compatibility. @@ -7568,7 +7657,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, << FD->getLocation()), /*TemplatesSupported=*/true, /*ConstexprSupported=*/false, /*CLinkageMayDiffer=*/true)) - return None; + return std::nullopt; return std::make_pair(FD, cast<Expr>(DRE)); } @@ -7576,9 +7665,8 @@ void Sema::ActOnOpenMPDeclareVariantDirective( FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef<Expr *> AdjustArgsNothing, ArrayRef<Expr *> AdjustArgsNeedDevicePtr, - ArrayRef<OMPDeclareVariantAttr::InteropType> AppendArgs, - SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, - SourceRange SR) { + ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc, + SourceLocation AppendArgsLoc, SourceRange SR) { // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions] // An adjust_args clause or append_args clause can only be specified if the @@ -7638,8 +7726,7 @@ void Sema::ActOnOpenMPDeclareVariantDirective( AdjustArgsNothing.size(), const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()), AdjustArgsNeedDevicePtr.size(), - const_cast<OMPDeclareVariantAttr::InteropType *>(AppendArgs.data()), - AppendArgs.size(), SR); + const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR); FD->addAttr(NewAttr); } @@ -7750,7 +7837,7 @@ class OpenMPIterationSpaceChecker { /// UB > Var /// UB >= Var /// This will have no value when the condition is != - llvm::Optional<bool> TestIsLessOp; + std::optional<bool> TestIsLessOp; /// This flag is true when condition is strict ( < or > ). bool TestIsStrictOp = false; /// This flag is true when step is subtracted on each iteration. @@ -7759,12 +7846,13 @@ class OpenMPIterationSpaceChecker { const ValueDecl *DepDecl = nullptr; /// Contains number of loop (starts from 1) on which loop counter init /// expression of this loop depends on. - Optional<unsigned> InitDependOnLC; + std::optional<unsigned> InitDependOnLC; /// Contains number of loop (starts from 1) on which loop counter condition /// expression of this loop depends on. - Optional<unsigned> CondDependOnLC; + std::optional<unsigned> CondDependOnLC; /// Checks if the provide statement depends on the loop counter. - Optional<unsigned> doesDependOnLoopCounter(const Stmt *S, bool IsInitializer); + std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S, + bool IsInitializer); /// Original condition required for checking of the exit condition for /// non-rectangular loop. Expr *Condition = nullptr; @@ -7847,7 +7935,7 @@ private: bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB, bool EmitDiags); /// Helper to set upper bound. - bool setUB(Expr *NewUB, llvm::Optional<bool> LessOp, bool StrictOp, + bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp, SourceRange SR, SourceLocation SL); /// Helper to set loop increment. bool setStep(Expr *NewStep, bool Subtract); @@ -7885,8 +7973,7 @@ bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl, return false; } -bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, - llvm::Optional<bool> LessOp, +bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp, SourceRange SR, SourceLocation SL) { // State consistency checking to ensure correct usage. @@ -7929,7 +8016,7 @@ 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. - Optional<llvm::APSInt> Result = + std::optional<llvm::APSInt> Result = NewStep->getIntegerConstantExpr(SemaRef.Context); bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation(); bool IsConstNeg = @@ -7941,19 +8028,18 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { // != with increment is treated as <; != with decrement is treated as > if (!TestIsLessOp) TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract); - if (UB && - (IsConstZero || - (TestIsLessOp.value() ? (IsConstNeg || (IsUnsigned && Subtract)) - : (IsConstPos || (IsUnsigned && !Subtract))))) { + if (UB && (IsConstZero || + (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract)) + : (IsConstPos || (IsUnsigned && !Subtract))))) { SemaRef.Diag(NewStep->getExprLoc(), diag::err_omp_loop_incr_not_compatible) - << LCDecl << TestIsLessOp.value() << NewStep->getSourceRange(); + << LCDecl << *TestIsLessOp << NewStep->getSourceRange(); SemaRef.Diag(ConditionLoc, diag::note_omp_loop_cond_requres_compatible_incr) - << TestIsLessOp.value() << ConditionSrcRange; + << *TestIsLessOp << ConditionSrcRange; return true; } - if (TestIsLessOp.value() == Subtract) { + if (*TestIsLessOp == Subtract) { NewStep = SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep) .get(); @@ -8064,7 +8150,7 @@ public: }; } // namespace -Optional<unsigned> +std::optional<unsigned> OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S, bool IsInitializer) { // Check for the non-rectangular loops. @@ -8074,7 +8160,7 @@ OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S, DepDecl = LoopStmtChecker.getDepDecl(); return LoopStmtChecker.getBaseLoopId(); } - return llvm::None; + return std::nullopt; } bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) { @@ -8200,10 +8286,10 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { Condition = S; S = getExprAsWritten(S); SourceLocation CondLoc = S->getBeginLoc(); - auto &&CheckAndSetCond = [this, IneqCondIsCanonical]( - BinaryOperatorKind Opcode, const Expr *LHS, - const Expr *RHS, SourceRange SR, - SourceLocation OpLoc) -> llvm::Optional<bool> { + auto &&CheckAndSetCond = + [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS, + const Expr *RHS, SourceRange SR, + SourceLocation OpLoc) -> std::optional<bool> { if (BinaryOperator::isRelationalOp(Opcode)) { if (getInitLCDecl(LHS) == LCDecl) return setUB(const_cast<Expr *>(RHS), @@ -8215,12 +8301,12 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) { (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc); } else if (IneqCondIsCanonical && Opcode == BO_NE) { return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS), - /*LessOp=*/llvm::None, + /*LessOp=*/std::nullopt, /*StrictOp=*/true, SR, OpLoc); } - return llvm::None; + return std::nullopt; }; - llvm::Optional<bool> Res; + std::optional<bool> Res; if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) { CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm(); Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(), @@ -8383,12 +8469,12 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, return nullptr; llvm::APSInt LRes, SRes; bool IsLowerConst = false, IsStepConst = false; - if (Optional<llvm::APSInt> Res = + if (std::optional<llvm::APSInt> Res = Lower->getIntegerConstantExpr(SemaRef.Context)) { LRes = *Res; IsLowerConst = true; } - if (Optional<llvm::APSInt> Res = + if (std::optional<llvm::APSInt> Res = Step->getIntegerConstantExpr(SemaRef.Context)) { SRes = *Res; IsStepConst = true; @@ -8427,7 +8513,7 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, } llvm::APSInt URes; bool IsUpperConst = false; - if (Optional<llvm::APSInt> Res = + if (std::optional<llvm::APSInt> Res = Upper->getIntegerConstantExpr(SemaRef.Context)) { URes = *Res; IsUpperConst = true; @@ -8708,8 +8794,8 @@ Expr *OpenMPIterationSpaceChecker::buildNumIterations( UBVal = MinUB.get(); } } - Expr *UBExpr = TestIsLessOp.value() ? UBVal : LBVal; - Expr *LBExpr = TestIsLessOp.value() ? LBVal : UBVal; + Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal; + Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal; Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get(); Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get(); if (!Upper || !Lower) @@ -8772,12 +8858,12 @@ std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues( // init value. Expr *MinExpr = nullptr; Expr *MaxExpr = nullptr; - Expr *LBExpr = TestIsLessOp.value() ? LB : UB; - Expr *UBExpr = TestIsLessOp.value() ? UB : LB; - bool LBNonRect = TestIsLessOp.value() ? InitDependOnLC.has_value() - : CondDependOnLC.has_value(); - bool UBNonRect = TestIsLessOp.value() ? CondDependOnLC.has_value() - : InitDependOnLC.has_value(); + Expr *LBExpr = *TestIsLessOp ? LB : UB; + Expr *UBExpr = *TestIsLessOp ? UB : LB; + bool LBNonRect = + *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value(); + bool UBNonRect = + *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value(); Expr *Lower = LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get(); Expr *Upper = @@ -8899,11 +8985,11 @@ Expr *OpenMPIterationSpaceChecker::buildPreCond( if (!NewLB.isUsable() || !NewUB.isUsable()) return nullptr; - ExprResult CondExpr = SemaRef.BuildBinOp( - S, DefaultLoc, - TestIsLessOp.value() ? (TestIsStrictOp ? BO_LT : BO_LE) - : (TestIsStrictOp ? BO_GT : BO_GE), - NewLB.get(), NewUB.get()); + ExprResult CondExpr = + SemaRef.BuildBinOp(S, DefaultLoc, + *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE) + : (TestIsStrictOp ? BO_GT : BO_GE), + NewLB.get(), NewUB.get()); if (CondExpr.isUsable()) { if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(), SemaRef.Context.BoolTy)) @@ -8979,9 +9065,9 @@ Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData( return nullptr; // Upper - Lower Expr *Upper = - TestIsLessOp.value() ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get(); + *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get(); Expr *Lower = - TestIsLessOp.value() ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; + *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt; if (!Upper || !Lower) return nullptr; @@ -9383,7 +9469,7 @@ 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; - if (Optional<llvm::APSInt> Result = + if (std::optional<llvm::APSInt> Result = E->getIntegerConstantExpr(SemaRef.Context)) return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits); return false; @@ -11012,9 +11098,50 @@ StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc, return OMPBarrierDirective::Create(Context, StartLoc, EndLoc); } +StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc, + bool InExContext) { + const OMPAtClause *AtC = + OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses); + + if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) { + Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier); + return StmtError(); + } + + const OMPSeverityClause *SeverityC = + OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses); + const OMPMessageClause *MessageC = + OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses); + Expr *ME = MessageC ? MessageC->getMessageString() : nullptr; + + if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) { + if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning) + Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded) + << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING"); + else + Diag(StartLoc, diag::err_diagnose_if_succeeded) + << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR"); + if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning) + return StmtError(); + } + return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses); +} + StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc) { + const OMPNowaitClause *NowaitC = + OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses); + bool HasDependC = + !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses) + .empty(); + if (NowaitC && !HasDependC) { + Diag(StartLoc, diag::err_omp_nowait_clause_without_depend); + return StmtError(); + } + return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses); } @@ -11569,6 +11696,9 @@ protected: static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo, bool ShouldBeLValue, bool ShouldBeInteger = false) { + if (E->isInstantiationDependent()) + return true; + if (ShouldBeLValue && !E->isLValue()) { ErrorInfo.Error = ErrorTy::XNotLValue; ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); @@ -11576,25 +11706,23 @@ protected: return false; } - if (!E->isInstantiationDependent()) { - QualType QTy = E->getType(); - if (!QTy->isScalarType()) { - ErrorInfo.Error = ErrorTy::NotScalar; - ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); - ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); - return false; - } - if (ShouldBeInteger && !QTy->isIntegerType()) { - ErrorInfo.Error = ErrorTy::NotInteger; - ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); - ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); - return false; - } + QualType QTy = E->getType(); + if (!QTy->isScalarType()) { + ErrorInfo.Error = ErrorTy::NotScalar; + ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); + ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); + return false; + } + if (ShouldBeInteger && !QTy->isIntegerType()) { + ErrorInfo.Error = ErrorTy::NotInteger; + ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc(); + ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange(); + return false; } return true; } -}; + }; bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo) { @@ -12174,17 +12302,33 @@ bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S, Stmt *UpdateStmt = nullptr; Stmt *CondUpdateStmt = nullptr; + Stmt *CondExprStmt = nullptr; if (auto *BO = dyn_cast<BinaryOperator>(S1)) { - // { v = x; cond-update-stmt } or form 45. - UpdateStmt = S1; - CondUpdateStmt = S2; - // Check if form 45. - if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) && - isa<IfStmt>(S2)) - return checkForm45(CS, ErrorInfo); - // It cannot be set before we the check for form45. - IsPostfixUpdate = true; + // It could be one of the following cases: + // { v = x; cond-update-stmt } + // { v = x; cond-expr-stmt } + // { cond-expr-stmt; v = x; } + // form 45 + if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) || + isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) { + // check if form 45 + if (isa<IfStmt>(S2)) + return checkForm45(CS, ErrorInfo); + // { cond-expr-stmt; v = x; } + CondExprStmt = S1; + UpdateStmt = S2; + } else { + IsPostfixUpdate = true; + UpdateStmt = S1; + if (isa<IfStmt>(S2)) { + // { v = x; cond-update-stmt } + CondUpdateStmt = S2; + } else { + // { v = x; cond-expr-stmt } + CondExprStmt = S2; + } + } } else { // { cond-update-stmt v = x; } UpdateStmt = S2; @@ -12200,10 +12344,7 @@ bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S, return false; } - if (!checkCondUpdateStmt(IS, ErrorInfo)) - return false; - - return true; + return checkCondUpdateStmt(IS, ErrorInfo); }; // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt. @@ -12236,7 +12377,9 @@ bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S, return true; }; - if (!CheckCondUpdateStmt(CondUpdateStmt)) + if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt)) + return false; + if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo)) return false; if (!CheckUpdateStmt(UpdateStmt)) return false; @@ -12277,7 +12420,7 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, case OMPC_write: case OMPC_update: MutexClauseEncountered = true; - LLVM_FALLTHROUGH; + [[fallthrough]]; case OMPC_capture: case OMPC_compare: { if (AtomicKind != OMPC_unknown && MutexClauseEncountered) { @@ -15049,12 +15192,6 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_priority: Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc); break; - case OMPC_grainsize: - Res = ActOnOpenMPGrainsizeClause(Expr, StartLoc, LParenLoc, EndLoc); - break; - case OMPC_num_tasks: - Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc); - break; case OMPC_hint: Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc); break; @@ -15076,9 +15213,17 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_partial: Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_message: + Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc); + break; case OMPC_align: Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_ompx_dyn_cgroup_mem: + Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_grainsize: + case OMPC_num_tasks: case OMPC_device: case OMPC_if: case OMPC_default: @@ -15135,6 +15280,8 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_match: case OMPC_nontemporal: case OMPC_order: + case OMPC_at: + case OMPC_severity: case OMPC_destroy: case OMPC_inclusive: case OMPC_exclusive: @@ -15166,7 +15313,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( CaptureRegion = OMPD_parallel; break; } - LLVM_FALLTHROUGH; + [[fallthrough]]; case OMPD_target_parallel: case OMPD_target_parallel_for: case OMPD_target_parallel_loop: @@ -15181,7 +15328,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( CaptureRegion = OMPD_parallel; break; } - LLVM_FALLTHROUGH; + [[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. @@ -15194,7 +15341,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( CaptureRegion = OMPD_parallel; break; } - LLVM_FALLTHROUGH; + [[fallthrough]]; case OMPD_teams_distribute_parallel_for: CaptureRegion = OMPD_teams; break; @@ -15289,6 +15436,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15377,6 +15525,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15473,6 +15622,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15514,6 +15664,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( break; case OMPC_thread_limit: switch (DKind) { + case OMPD_target: case OMPD_target_teams: case OMPD_target_teams_distribute: case OMPD_target_teams_distribute_simd: @@ -15555,7 +15706,6 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_parallel_loop: - case OMPD_target: case OMPD_target_simd: case OMPD_target_parallel: case OMPD_target_parallel_for: @@ -15564,6 +15714,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15652,6 +15803,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15743,6 +15895,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15785,6 +15938,26 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( llvm_unreachable("Unknown OpenMP directive"); } break; + case OMPC_ompx_dyn_cgroup_mem: + switch (DKind) { + case OMPD_target: + case OMPD_target_simd: + case OMPD_target_teams: + case OMPD_target_parallel: + case OMPD_target_teams_distribute: + case OMPD_target_teams_distribute_simd: + case OMPD_target_parallel_for: + case OMPD_target_parallel_for_simd: + case OMPD_target_parallel_loop: + case OMPD_target_teams_distribute_parallel_for: + case OMPD_target_teams_distribute_parallel_for_simd: + case OMPD_target_teams_loop: + CaptureRegion = OMPD_target; + break; + default: + llvm_unreachable("Unknown OpenMP directive"); + } + break; case OMPC_device: switch (DKind) { case OMPD_target_update: @@ -15837,6 +16010,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -15928,6 +16102,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPD_threadprivate: case OMPD_allocate: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -16052,6 +16227,9 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_match: case OMPC_nontemporal: case OMPC_order: + case OMPC_at: + case OMPC_severity: + case OMPC_message: case OMPC_destroy: case OMPC_detach: case OMPC_inclusive: @@ -16190,7 +16368,7 @@ isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, ValExpr = Value.get(); // The expression must evaluate to a non-negative integer value. - if (Optional<llvm::APSInt> Result = + if (std::optional<llvm::APSInt> Result = ValExpr->getIntegerConstantExpr(SemaRef.Context)) { if (Result->isSigned() && !((!StrictlyPositive && Result->isNonNegative()) || @@ -16320,10 +16498,22 @@ OMPClause *Sema::ActOnOpenMPSimdlenClause(Expr *Len, SourceLocation StartLoc, /// Tries to find omp_allocator_handle_t type. static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) { - QualType OMPAllocatorHandleT = Stack->getOMPAllocatorHandleT(); - if (!OMPAllocatorHandleT.isNull()) + if (!Stack->getOMPAllocatorHandleT().isNull()) return true; - // Build the predefined allocator expressions. + + // Set the allocator handle type. + IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t"); + ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope()); + if (!PT.getAsOpaquePtr() || PT.get().isNull()) { + S.Diag(Loc, diag::err_omp_implied_type_not_found) + << "omp_allocator_handle_t"; + return false; + } + QualType AllocatorHandleEnumTy = PT.get(); + AllocatorHandleEnumTy.addConst(); + Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy); + + // Fill the predefined allocator map. bool ErrorFound = false; for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) { auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I); @@ -16343,9 +16533,10 @@ static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, ErrorFound = true; break; } - if (OMPAllocatorHandleT.isNull()) - OMPAllocatorHandleT = AllocatorType; - if (!S.getASTContext().hasSameType(OMPAllocatorHandleT, AllocatorType)) { + Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy, + Sema::AA_Initializing, + /* AllowExplicit */ true); + if (!Res.isUsable()) { ErrorFound = true; break; } @@ -16356,8 +16547,7 @@ static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, << "omp_allocator_handle_t"; return false; } - OMPAllocatorHandleT.addConst(); - Stack->setOMPAllocatorHandleT(OMPAllocatorHandleT); + return true; } @@ -16442,10 +16632,6 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; - case OMPC_order: - Res = ActOnOpenMPOrderClause(static_cast<OpenMPOrderClauseKind>(Argument), - ArgumentLoc, StartLoc, LParenLoc, EndLoc); - break; case OMPC_update: Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); @@ -16454,6 +16640,15 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; + case OMPC_at: + Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument), + ArgumentLoc, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_severity: + Res = ActOnOpenMPSeverityClause( + static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc, + LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -16529,6 +16724,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: + case OMPC_message: default: llvm_unreachable("Clause is not allowed."); } @@ -16537,13 +16733,12 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, - ArrayRef<unsigned> Exclude = llvm::None) { + ArrayRef<unsigned> Exclude = std::nullopt) { SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); unsigned Skipped = Exclude.size(); - auto S = Exclude.begin(), E = Exclude.end(); for (unsigned I = First; I < Last; ++I) { - if (std::find(S, E, I) != E) { + if (llvm::is_contained(Exclude, I)) { --Skipped; continue; } @@ -16633,22 +16828,87 @@ OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause( LParenLoc, EndLoc); } -OMPClause *Sema::ActOnOpenMPOrderClause(OpenMPOrderClauseKind Kind, - SourceLocation KindKwLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { - if (Kind == OMPC_ORDER_unknown) { +OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, + SourceLocation KindKwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + if (Kind == OMPC_AT_unknown) { + Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_at, /*First=*/0, + /*Last=*/OMPC_AT_unknown) + << getOpenMPClauseName(OMPC_at); + return nullptr; + } + return new (Context) + OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, + SourceLocation KindKwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + if (Kind == OMPC_SEVERITY_unknown) { + Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_severity, /*First=*/0, + /*Last=*/OMPC_SEVERITY_unknown) + << getOpenMPClauseName(OMPC_severity); + return nullptr; + } + return new (Context) + OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPMessageClause(Expr *ME, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + assert(ME && "NULL expr in Message clause"); + if (!isa<StringLiteral>(ME)) { + Diag(ME->getBeginLoc(), diag::warn_clause_expected_string) + << getOpenMPClauseName(OMPC_message); + return nullptr; + } + return new (Context) OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc); +} + +OMPClause *Sema::ActOnOpenMPOrderClause( + OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, + SourceLocation KindLoc, SourceLocation EndLoc) { + if (Kind != OMPC_ORDER_concurrent || + (LangOpts.OpenMP < 51 && MLoc.isValid())) { + // Kind should be concurrent, + // Modifiers introduced in OpenMP 5.1 static_assert(OMPC_ORDER_unknown > 0, "OMPC_ORDER_unknown not greater than 0"); - Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) - << getListOfPossibleValues(OMPC_order, /*First=*/0, + + Diag(KindLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_order, + /*First=*/0, /*Last=*/OMPC_ORDER_unknown) << getOpenMPClauseName(OMPC_order); return nullptr; } - return new (Context) - OMPOrderClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); + if (LangOpts.OpenMP >= 51) { + if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) { + Diag(MLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_order, + /*First=*/OMPC_ORDER_MODIFIER_unknown + 1, + /*Last=*/OMPC_ORDER_MODIFIER_last) + << getOpenMPClauseName(OMPC_order); + } else { + DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true); + if (DSAStack->getCurScope()) { + // mark the current scope with 'order' flag + unsigned existingFlags = DSAStack->getCurScope()->getFlags(); + DSAStack->getCurScope()->setFlags(existingFlags | + Scope::OpenMPOrderClauseScope); + } + } + } + return new (Context) OMPOrderClause(Kind, KindLoc, StartLoc, LParenLoc, + EndLoc, Modifier, MLoc); } OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, @@ -16760,12 +17020,33 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind], EndLoc); break; + case OMPC_order: + enum { OrderModifier, OrderKind }; + Res = ActOnOpenMPOrderClause( + static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]), + static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc, + LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc); + break; case OMPC_device: assert(Argument.size() == 1 && ArgumentLoc.size() == 1); Res = ActOnOpenMPDeviceClause( static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr, StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); break; + case OMPC_grainsize: + assert(Argument.size() == 1 && ArgumentLoc.size() == 1 && + "Modifier for grainsize clause and its location are expected."); + Res = ActOnOpenMPGrainsizeClause( + static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr, + StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); + break; + case OMPC_num_tasks: + assert(Argument.size() == 1 && ArgumentLoc.size() == 1 && + "Modifier for num_tasks clause and its location are expected."); + Res = ActOnOpenMPNumTasksClause( + static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr, + StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc); + break; case OMPC_final: case OMPC_num_threads: case OMPC_safelen: @@ -16811,9 +17092,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_num_teams: case OMPC_thread_limit: case OMPC_priority: - case OMPC_grainsize: case OMPC_nogroup: - case OMPC_num_tasks: case OMPC_hint: case OMPC_unknown: case OMPC_uniform: @@ -16831,7 +17110,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_device_type: case OMPC_match: case OMPC_nontemporal: - case OMPC_order: + case OMPC_at: + case OMPC_severity: + case OMPC_message: case OMPC_destroy: case OMPC_novariants: case OMPC_nocontext: @@ -16935,7 +17216,7 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - if (Optional<llvm::APSInt> Result = + if (std::optional<llvm::APSInt> Result = ValExpr->getIntegerConstantExpr(Context)) { if (Result->isSigned() && !Result->isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) @@ -17088,6 +17369,9 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_match: case OMPC_nontemporal: case OMPC_order: + case OMPC_at: + case OMPC_severity: + case OMPC_message: case OMPC_novariants: case OMPC_nocontext: case OMPC_detach: @@ -17096,6 +17380,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_uses_allocators: case OMPC_affinity: case OMPC_when: + case OMPC_ompx_dyn_cgroup_mem: default: llvm_unreachable("Clause is not allowed."); } @@ -17247,32 +17532,28 @@ StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses, // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] // Each interop-var may be specified for at most one action-clause of each // interop construct. - llvm::SmallPtrSet<const VarDecl *, 4> InteropVars; - for (const OMPClause *C : Clauses) { + llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars; + for (OMPClause *C : Clauses) { OpenMPClauseKind ClauseKind = C->getClauseKind(); - const DeclRefExpr *DRE = nullptr; - SourceLocation VarLoc; + std::pair<ValueDecl *, bool> DeclResult; + SourceLocation ELoc; + SourceRange ERange; if (ClauseKind == OMPC_init) { - const auto *IC = cast<OMPInitClause>(C); - VarLoc = IC->getVarLoc(); - DRE = dyn_cast_or_null<DeclRefExpr>(IC->getInteropVar()); + auto *E = cast<OMPInitClause>(C)->getInteropVar(); + DeclResult = getPrivateItem(*this, E, ELoc, ERange); } else if (ClauseKind == OMPC_use) { - const auto *UC = cast<OMPUseClause>(C); - VarLoc = UC->getVarLoc(); - DRE = dyn_cast_or_null<DeclRefExpr>(UC->getInteropVar()); + auto *E = cast<OMPUseClause>(C)->getInteropVar(); + DeclResult = getPrivateItem(*this, E, ELoc, ERange); } else if (ClauseKind == OMPC_destroy) { - const auto *DC = cast<OMPDestroyClause>(C); - VarLoc = DC->getVarLoc(); - DRE = dyn_cast_or_null<DeclRefExpr>(DC->getInteropVar()); + auto *E = cast<OMPDestroyClause>(C)->getInteropVar(); + DeclResult = getPrivateItem(*this, E, ELoc, ERange); } - if (!DRE) - continue; - - if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) { - if (!InteropVars.insert(VD->getCanonicalDecl()).second) { - Diag(VarLoc, diag::err_omp_interop_var_multiple_actions) << VD; + if (DeclResult.first) { + if (!InteropVars.insert(DeclResult.first).second) { + Diag(ELoc, diag::err_omp_interop_var_multiple_actions) + << DeclResult.first; return StmtError(); } } @@ -17284,16 +17565,20 @@ StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses, static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind) { - if (InteropVarExpr->isValueDependent() || InteropVarExpr->isTypeDependent() || - InteropVarExpr->isInstantiationDependent() || - InteropVarExpr->containsUnexpandedParameterPack()) + SourceLocation ELoc; + SourceRange ERange; + Expr *RefExpr = InteropVarExpr; + auto Res = + getPrivateItem(SemaRef, RefExpr, ELoc, ERange, + /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t"); + + if (Res.second) { + // It will be analyzed later. return true; + } - const auto *DRE = dyn_cast<DeclRefExpr>(InteropVarExpr); - if (!DRE || !isa<VarDecl>(DRE->getDecl())) { - SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected) << 0; + if (!Res.first) return false; - } // Interop variable should be of type omp_interop_t. bool HasError = false; @@ -17335,8 +17620,7 @@ static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, } OMPClause * -Sema::ActOnOpenMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs, - bool IsTarget, bool IsTargetSync, +Sema::ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) { @@ -17345,7 +17629,7 @@ Sema::ActOnOpenMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs, // Check prefer_type values. These foreign-runtime-id values are either // string literals or constant integral expressions. - for (const Expr *E : PrefExprs) { + for (const Expr *E : InteropInfo.PreferTypes) { if (E->isValueDependent() || E->isTypeDependent() || E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) continue; @@ -17357,9 +17641,8 @@ Sema::ActOnOpenMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs, return nullptr; } - return OMPInitClause::Create(Context, InteropVar, PrefExprs, IsTarget, - IsTargetSync, StartLoc, LParenLoc, VarLoc, - EndLoc); + return OMPInitClause::Create(Context, InteropVar, InteropInfo, StartLoc, + LParenLoc, VarLoc, EndLoc); } OMPClause *Sema::ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, @@ -17549,7 +17832,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown && "Unexpected map modifier."); Res = ActOnOpenMPMapClause( - Data.MapTypeModifiers, Data.MapTypeModifiersLoc, + Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit, ExtraModifierLoc, ColonLoc, VarList, Locs); @@ -17644,6 +17927,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, case OMPC_device_type: case OMPC_match: case OMPC_order: + case OMPC_at: + case OMPC_severity: + case OMPC_message: case OMPC_destroy: case OMPC_novariants: case OMPC_nocontext: @@ -18417,7 +18703,7 @@ static T filterLookupForUDReductionAndMapper( static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) { assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); - for (auto RD : D->redecls()) { + for (auto *RD : D->redecls()) { // Don't bother with extra checks if we already know this one isn't visible. if (RD == D) continue; @@ -19744,7 +20030,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). - if (Optional<llvm::APSInt> Result = + if (std::optional<llvm::APSInt> Result = StepExpr->getIntegerConstantExpr(Context)) { if (!Result->isNegative() && !Result->isStrictlyPositive()) Diag(StepLoc, diag::warn_omp_linear_step_zero) @@ -20927,8 +21213,8 @@ public: } // Pointer arithmetic is the only thing we expect to happen here so after we - // make sure the binary operator is a pointer type, the we only thing need - // to to is to visit the subtree that has the same type as root (so that we + // make sure the binary operator is a pointer type, the only thing we need + // to do is to visit the subtree that has the same type as root (so that we // know the other subtree is just an offset) Expr *LE = BO->getLHS()->IgnoreParenImpCasts(); Expr *RE = BO->getRHS()->IgnoreParenImpCasts(); @@ -21403,7 +21689,7 @@ static void checkMappableExpressionList( CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef<Expr *> UnresolvedMappers, OpenMPMapClauseKind MapType = OMPC_MAP_unknown, - ArrayRef<OpenMPMapModifierKind> Modifiers = None, + ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt, bool IsMapTypeImplicit = false, bool NoDiagnose = false) { // We only expect mappable expressions in 'to', 'from', and 'map' clauses. assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) && @@ -21603,10 +21889,12 @@ static void checkMappableExpressionList( // target enter data // OpenMP [2.10.2, Restrictions, p. 99] // A map-type must be specified in all map clauses and must be either - // to or alloc. + // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if + // no map type is present. OpenMPDirectiveKind DKind = DSAS->getCurrentDirective(); if (DKind == OMPD_target_enter_data && - !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc)) { + !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc || + SemaRef.getLangOpts().OpenMP >= 52)) { SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) << (IsMapTypeImplicit ? 1 : 0) << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) @@ -21617,10 +21905,11 @@ static void checkMappableExpressionList( // target exit_data // OpenMP [2.10.3, Restrictions, p. 102] // A map-type must be specified in all map clauses and must be either - // from, release, or delete. + // from, release, or delete. Starting with OpenMP 5.2 the default map + // type is `from` if no map type is present. if (DKind == OMPD_target_exit_data && !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release || - MapType == OMPC_MAP_delete)) { + MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) { SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive) << (IsMapTypeImplicit ? 1 : 0) << getOpenMPSimpleClauseTypeName(OMPC_map, MapType) @@ -21698,7 +21987,7 @@ static void checkMappableExpressionList( /*WhereFoundClauseKind=*/OMPC_map); // Save the components and declaration to create the clause. For purposes of - // the clause creation, any component list that has has base 'this' uses + // the clause creation, any component list that has base 'this' uses // null as base declaration. MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1); MVLI.VarComponents.back().append(CurComponents.begin(), @@ -21709,7 +21998,7 @@ static void checkMappableExpressionList( } OMPClause *Sema::ActOnOpenMPMapClause( - ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, + Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers, ArrayRef<SourceLocation> MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, @@ -21719,9 +22008,14 @@ OMPClause *Sema::ActOnOpenMPMapClause( OpenMPMapModifierKind Modifiers[] = { OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown, - OMPC_MAP_MODIFIER_unknown}; + OMPC_MAP_MODIFIER_unknown, OMPC_MAP_MODIFIER_unknown}; SourceLocation ModifiersLoc[NumberOfOMPMapClauseModifiers]; + if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType( + BuiltinType::OMPIterator)) + Diag(IteratorModifier->getExprLoc(), + diag::err_omp_map_modifier_not_iterator); + // Process map-type-modifiers, flag errors for duplicate modifiers. unsigned Count = 0; for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) { @@ -21745,11 +22039,11 @@ OMPClause *Sema::ActOnOpenMPMapClause( // We need to produce a map clause even if we don't have variables so that // other diagnostics related with non-existing map clauses are accurate. - return OMPMapClause::Create(Context, Locs, MVLI.ProcessedVarList, - MVLI.VarBaseDeclarations, MVLI.VarComponents, - MVLI.UDMapperList, Modifiers, ModifiersLoc, - MapperIdScopeSpec.getWithLocInContext(Context), - MapperId, MapType, IsMapTypeImplicit, MapLoc); + return OMPMapClause::Create( + Context, Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations, + MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers, + ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(Context), MapperId, + MapType, IsMapTypeImplicit, MapLoc); } QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, @@ -22143,6 +22437,11 @@ Sema::ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, return E; } +void Sema::ActOnOpenMPIteratorVarDecl(VarDecl *VD) { + if (DSAStack->getDeclareMapperVarRef()) + DSAStack->addIteratorVarDecl(VD); +} + bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const { assert(LangOpts.OpenMP && "Expected OpenMP mode."); const Expr *Ref = DSAStack->getDeclareMapperVarRef(); @@ -22151,6 +22450,8 @@ bool Sema::isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const { return true; if (VD->isUsableInConstantExpressions(Context)) return true; + if (LangOpts.OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD)) + return true; return false; } return true; @@ -22235,10 +22536,21 @@ OMPClause *Sema::ActOnOpenMPPriorityClause(Expr *Priority, StartLoc, LParenLoc, EndLoc); } -OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { +OMPClause *Sema::ActOnOpenMPGrainsizeClause( + OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ModifierLoc, SourceLocation EndLoc) { + assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) && + "Unexpected grainsize modifier in OpenMP < 51."); + + if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) { + std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0, + OMPC_GRAINSIZE_unknown); + Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) + << Values << getOpenMPClauseName(OMPC_grainsize); + return nullptr; + } + Expr *ValExpr = Grainsize; Stmt *HelperValStmt = nullptr; OpenMPDirectiveKind CaptureRegion = OMPD_unknown; @@ -22246,20 +22558,33 @@ OMPClause *Sema::ActOnOpenMPGrainsizeClause(Expr *Grainsize, // OpenMP [2.9.2, taskloop Constrcut] // The parameter of the grainsize clause must be a positive integer // expression. - if (!isNonNegativeIntegerValue( - ValExpr, *this, OMPC_grainsize, - /*StrictlyPositive=*/true, /*BuildCapture=*/true, - DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt)) + if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_grainsize, + /*StrictlyPositive=*/true, + /*BuildCapture=*/true, + DSAStack->getCurrentDirective(), + &CaptureRegion, &HelperValStmt)) return nullptr; - return new (Context) OMPGrainsizeClause(ValExpr, HelperValStmt, CaptureRegion, - StartLoc, LParenLoc, EndLoc); + return new (Context) + OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, + StartLoc, LParenLoc, ModifierLoc, EndLoc); } -OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { +OMPClause *Sema::ActOnOpenMPNumTasksClause( + OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ModifierLoc, SourceLocation EndLoc) { + assert((ModifierLoc.isInvalid() || LangOpts.OpenMP >= 51) && + "Unexpected num_tasks modifier in OpenMP < 51."); + + if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) { + std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0, + OMPC_NUMTASKS_unknown); + Diag(ModifierLoc, diag::err_omp_unexpected_clause_value) + << Values << getOpenMPClauseName(OMPC_num_tasks); + return nullptr; + } + Expr *ValExpr = NumTasks; Stmt *HelperValStmt = nullptr; OpenMPDirectiveKind CaptureRegion = OMPD_unknown; @@ -22273,8 +22598,9 @@ OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks, DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt)) return nullptr; - return new (Context) OMPNumTasksClause(ValExpr, HelperValStmt, CaptureRegion, - StartLoc, LParenLoc, EndLoc); + return new (Context) + OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, + StartLoc, LParenLoc, ModifierLoc, EndLoc); } OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, @@ -22384,7 +22710,7 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - if (Optional<llvm::APSInt> Result = + if (std::optional<llvm::APSInt> Result = ValExpr->getIntegerConstantExpr(Context)) { if (Result->isSigned() && !Result->isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) @@ -22583,29 +22909,29 @@ void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, const unsigned Level = -1; auto *VD = cast<ValueDecl>(ND); - llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = + std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = OMPDeclareTargetDeclAttr::getActiveAttr(VD); - if (ActiveAttr && ActiveAttr.value()->getDevType() != DTCI.DT && - ActiveAttr.value()->getLevel() == Level) { + if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT && + (*ActiveAttr)->getLevel() == Level) { Diag(Loc, diag::err_omp_device_type_mismatch) << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT) << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr( - ActiveAttr.value()->getDevType()); + (*ActiveAttr)->getDevType()); return; } - if (ActiveAttr && ActiveAttr.value()->getMapType() != MT && - ActiveAttr.value()->getLevel() == Level) { + if (ActiveAttr && (*ActiveAttr)->getMapType() != MT && + (*ActiveAttr)->getLevel() == Level) { Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND; return; } - if (ActiveAttr && ActiveAttr.value()->getLevel() == Level) + if (ActiveAttr && (*ActiveAttr)->getLevel() == Level) return; Expr *IndirectE = nullptr; bool IsIndirect = false; if (DTCI.Indirect) { - IndirectE = DTCI.Indirect.value(); + IndirectE = *DTCI.Indirect; if (!IndirectE) IsIndirect = true; } @@ -22623,13 +22949,14 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, if (!D || !isa<VarDecl>(D)) return; auto *VD = cast<VarDecl>(D); - Optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy = + std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (SemaRef.LangOpts.OpenMP >= 50 && (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) || SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) && VD->hasGlobalStorage()) { - if (!MapTy || *MapTy != OMPDeclareTargetDeclAttr::MT_To) { + if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To && + *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) { // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions // If a lambda declaration and definition appears between a // declare target directive and the matching end declare target @@ -22678,7 +23005,7 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) D = FTD->getTemplatedDecl(); if (auto *FD = dyn_cast<FunctionDecl>(D)) { - llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = + std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD); if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) { Diag(IdLoc, diag::err_omp_function_in_link_clause); @@ -22696,22 +23023,25 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, // Checking declaration inside declare target region. if (isa<VarDecl>(D) || isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { - llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = + std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr = OMPDeclareTargetDeclAttr::getActiveAttr(VD); unsigned Level = DeclareTargetNesting.size(); - if (ActiveAttr && ActiveAttr.value()->getLevel() >= Level) + if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level) return; DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back(); Expr *IndirectE = nullptr; bool IsIndirect = false; if (DTCI.Indirect) { - IndirectE = DTCI.Indirect.value(); + IndirectE = *DTCI.Indirect; if (!IndirectE) IsIndirect = true; } auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, IndirectE, - IsIndirect, Level, SourceRange(DTCI.Loc, DTCI.Loc)); + Context, + getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter + : OMPDeclareTargetDeclAttr::MT_To, + DTCI.DT, IndirectE, IsIndirect, Level, + SourceRange(DTCI.Loc, DTCI.Loc)); D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(D, A); @@ -23065,13 +23395,17 @@ OMPClause *Sema::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList, // Store the components in the stack so that they can be used to check // against other clauses later on. + Expr *Component = SimpleRefExpr; + auto *VD = dyn_cast<VarDecl>(D); + if (VD && (isa<OMPArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) || + isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts()))) + Component = DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get(); OMPClauseMappableExprCommon::MappableComponent MC( - SimpleRefExpr, D, /*IsNonContiguous=*/false); + Component, D, /*IsNonContiguous=*/false); DSAStack->addMappableExpressionComponents( D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr); // Record the expression we've just processed. - auto *VD = dyn_cast<VarDecl>(D); if (!VD && !CurContext->isDependentContext()) { DeclRefExpr *Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true); @@ -23336,17 +23670,26 @@ OMPClause *Sema::ActOnOpenMPUsesAllocatorClause( AllocatorExpr = D.Allocator->IgnoreParenImpCasts(); auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr); bool IsPredefinedAllocator = false; - if (DRE) - IsPredefinedAllocator = PredefinedAllocators.count(DRE->getDecl()); - if (!DRE || - !(Context.hasSameUnqualifiedType( - AllocatorExpr->getType(), DSAStack->getOMPAllocatorHandleT()) || - Context.typesAreCompatible(AllocatorExpr->getType(), - DSAStack->getOMPAllocatorHandleT(), - /*CompareUnqualified=*/true)) || - (!IsPredefinedAllocator && - (AllocatorExpr->getType().isConstant(Context) || - !AllocatorExpr->isLValue()))) { + if (DRE) { + OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy = + getAllocatorKind(*this, DSAStack, AllocatorExpr); + IsPredefinedAllocator = + AllocatorTy != + OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc; + } + QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT(); + QualType AllocatorExprType = AllocatorExpr->getType(); + bool IsTypeCompatible = IsPredefinedAllocator; + IsTypeCompatible = IsTypeCompatible || + Context.hasSameUnqualifiedType(AllocatorExprType, + OMPAllocatorHandleT); + IsTypeCompatible = + IsTypeCompatible || + Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT); + bool IsNonConstantLValue = + !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue(); + if (!DRE || !IsTypeCompatible || + (!IsPredefinedAllocator && !IsNonConstantLValue)) { Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected) << "omp_allocator_handle_t" << (DRE ? 1 : 0) << AllocatorExpr->getType() << D.Allocator->getSourceRange(); @@ -23480,3 +23823,31 @@ OMPClause *Sema::ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, return OMPBindClause::Create(Context, Kind, KindLoc, StartLoc, LParenLoc, EndLoc); } + +OMPClause *Sema::ActOnOpenMPXDynCGroupMemClause(Expr *Size, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + Expr *ValExpr = Size; + Stmt *HelperValStmt = nullptr; + + // OpenMP [2.5, Restrictions] + // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer + // value. + if (!isNonNegativeIntegerValue(ValExpr, *this, OMPC_ompx_dyn_cgroup_mem, + /*StrictlyPositive=*/false)) + return nullptr; + + OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); + OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause( + DKind, OMPC_ompx_dyn_cgroup_mem, LangOpts.OpenMP); + if (CaptureRegion != OMPD_unknown && !CurContext->isDependentContext()) { + ValExpr = MakeFullExpr(ValExpr).get(); + llvm::MapVector<const Expr *, DeclRefExpr *> Captures; + ValExpr = tryBuildCapture(*this, ValExpr, Captures).get(); + HelperValStmt = buildPreInits(Context, Captures); + } + + return new (Context) OMPXDynCGroupMemClause( + ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc); +} |