(original) (raw)

diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index a1cb7fe359ebf..673c34bf08a4a 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -286,6 +286,8 @@ implementation. +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | memory management | 'allocator' modifier for allocate clause | :good:`done` | https://github.com/llvm/llvm-project/pull/114883 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ +| memory management | 'align' modifier for allocate clause | :good:`done` | https://github.com/llvm/llvm-project/pull/121814 | ++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | memory management | new memory management routines | :none:`unclaimed` | | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | memory management | changes to omp_alloctrait_key enum | :none:`unclaimed` | | diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5a48d6fbc01fa..214d11b797577 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1337,6 +1337,7 @@ OpenMP Support always build support for AMDGPU and NVPTX targets. - Added support for combined masked constructs 'omp parallel masked taskloop', 'omp parallel masked taskloop simd','omp masked taskloop' and 'omp masked taskloop simd' directive. +- Added support for align-modifier in 'allocate' clause. Improvements ^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index d2f5267e4da5e..b9088eff3bb52 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -498,6 +498,9 @@ class OMPAllocateClause final /// Allocator specified in the clause, or 'nullptr' if the default one is /// used. Expr *Allocator = nullptr; + /// Alignment specified in the clause, or 'nullptr' if the default one is + /// used. + Expr *Alignment = nullptr; /// Position of the ':' delimiter in the clause; SourceLocation ColonLoc; /// Modifier of 'allocate' clause. @@ -505,6 +508,41 @@ class OMPAllocateClause final /// Location of allocator modifier if any. SourceLocation AllocatorModifierLoc; + // ---------------------------------------------------------------------------- + + /// Modifiers for 'allocate' clause. + enum { FIRST, SECOND, NUM_MODIFIERS }; + OpenMPAllocateClauseModifier Modifiers[NUM_MODIFIERS]; + + /// Locations of modifiers. + SourceLocation ModifiersLoc[NUM_MODIFIERS]; + + /// Set the first allocate modifier. + /// + /// \param M Allocate modifier. + void setFirstAllocateModifier(OpenMPAllocateClauseModifier M) { + Modifiers[FIRST] = M; + } + + /// Set the second allocate modifier. + /// + /// \param M Allocate modifier. + void setSecondAllocateModifier(OpenMPAllocateClauseModifier M) { + Modifiers[SECOND] = M; + } + + /// Set location of the first allocate modifier. + void setFirstAllocateModifierLoc(SourceLocation Loc) { + ModifiersLoc[FIRST] = Loc; + } + + /// Set location of the second allocate modifier. + void setSecondAllocateModifierLoc(SourceLocation Loc) { + ModifiersLoc[SECOND] = Loc; + } + + // ---------------------------------------------------------------------------- + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. @@ -514,15 +552,20 @@ class OMPAllocateClause final /// \param EndLoc Ending location of the clause. /// \param N Number of the variables in the clause. OMPAllocateClause(SourceLocation StartLoc, SourceLocation LParenLoc, - Expr *Allocator, SourceLocation ColonLoc, - OpenMPAllocateClauseModifier AllocatorModifier, - SourceLocation AllocatorModifierLoc, SourceLocation EndLoc, + Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, + OpenMPAllocateClauseModifier Modifier1, + SourceLocation Modifier1Loc, + OpenMPAllocateClauseModifier Modifier2, + SourceLocation Modifier2Loc, SourceLocation EndLoc, unsigned N) : OMPVarListClause(llvm::omp::OMPC_allocate, StartLoc, LParenLoc, EndLoc, N), - Allocator(Allocator), ColonLoc(ColonLoc), - AllocatorModifier(AllocatorModifier), - AllocatorModifierLoc(AllocatorModifierLoc) {} + Allocator(Allocator), Alignment(Alignment), ColonLoc(ColonLoc) { + Modifiers[FIRST] = Modifier1; + Modifiers[SECOND] = Modifier2; + ModifiersLoc[FIRST] = Modifier1Loc; + ModifiersLoc[SECOND] = Modifier2Loc; + } /// Build an empty clause. /// @@ -530,7 +573,10 @@ class OMPAllocateClause final explicit OMPAllocateClause(unsigned N) : OMPVarListClause(llvm::omp::OMPC_allocate, SourceLocation(), SourceLocation(), - SourceLocation(), N) {} + SourceLocation(), N) { + Modifiers[FIRST] = OMPC_ALLOCATE_unknown; + Modifiers[SECOND] = OMPC_ALLOCATE_unknown; + } /// Sets location of ':' symbol in clause. void setColonLoc(SourceLocation CL) { ColonLoc = CL; } @@ -539,6 +585,7 @@ class OMPAllocateClause final void setAllocatorModifier(OpenMPAllocateClauseModifier AM) { AllocatorModifier = AM; } + void setAlignment(Expr *A) { Alignment = A; } public: /// Creates clause with a list of variables \a VL. @@ -554,19 +601,42 @@ class OMPAllocateClause final /// \param VL List of references to the variables. static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - Expr *Allocator, SourceLocation ColonLoc, - OpenMPAllocateClauseModifier AllocatorModifier, - SourceLocation AllocatorModifierLoc, SourceLocation EndLoc, - ArrayRef VL); + Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, + OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, + OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, + SourceLocation EndLoc, ArrayRef VL); /// Returns the allocator expression or nullptr, if no allocator is specified. Expr *getAllocator() const { return Allocator; } + /// Returns the alignment expression or nullptr, if no alignment specified. + Expr *getAlignment() const { return Alignment; } + /// Return 'allocate' modifier. OpenMPAllocateClauseModifier getAllocatorModifier() const { return AllocatorModifier; } + /// Get the first modifier of the clause. + OpenMPAllocateClauseModifier getFirstAllocateModifier() const { + return Modifiers[FIRST]; + } + + /// Get location of first modifier of the clause. + SourceLocation getFirstAllocateModifierLoc() const { + return ModifiersLoc[FIRST]; + } + + /// Get the second modifier of the clause. + OpenMPAllocateClauseModifier getSecondAllocateModifier() const { + return Modifiers[SECOND]; + } + + /// Get location of second modifier of the clause. + SourceLocation getSecondAllocateModifierLoc() const { + return ModifiersLoc[SECOND]; + } + /// Returns the location of the ':' delimiter. SourceLocation getColonLoc() const { return ColonLoc; } /// Return the location of the modifier. diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 86fcae209c40d..3309f59a981fc 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1658,6 +1658,8 @@ def warn_omp_depend_in_ordered_deprecated : Warning<"'depend' clause for" def warn_omp_invalid_attribute_for_ompx_attributes : Warning<"'ompx_attribute' clause only allows " "'amdgpu_flat_work_group_size', 'amdgpu_waves_per_eu', and 'launch_bounds'; " "%0 is ignored">, InGroup; +def err_omp_duplicate_modifier : Error<"duplicate modifier '%0' in '%1' clause">; +def err_omp_expected_modifier : Error<"expected modifier in '%0' clause">; // Pragma loop support. def err_pragma_loop_missing_argument : Error< diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 3f25e7aafe23b..76a861f416fd5 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -219,6 +219,7 @@ OPENMP_NUMTASKS_MODIFIER(strict) // Modifiers for 'allocate' clause. OPENMP_ALLOCATE_MODIFIER(allocator) +OPENMP_ALLOCATE_MODIFIER(align) // Modifiers for the 'doacross' clause. OPENMP_DOACROSS_MODIFIER(source) diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h index 900ad6ca6d66f..3e5da2a6abc01 100644 --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -230,6 +230,10 @@ enum OpenMPAllocateClauseModifier { OMPC_ALLOCATE_unknown }; +/// Number of allowed allocate-modifiers. +static constexpr unsigned NumberOfOMPAllocateClauseModifiers = + OMPC_ALLOCATE_unknown; + /// Contains 'interop' data for 'append_args' and 'init' clauses. class Expr; struct OMPInteropInfo final { diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index 3d1cc4fab1c10..a056a96f50233 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -1148,7 +1148,12 @@ class SemaOpenMP : public SemaBase { SourceLocation OmpAllMemoryLoc; SourceLocation StepModifierLoc; /// 'step' modifier location for linear clause - OpenMPAllocateClauseModifier AllocClauseModifier = OMPC_ALLOCATE_unknown; + SmallVector<openmpallocateclausemodifier, +="" numberofompallocateclausemodifiers=""> + AllocClauseModifiers; + SmallVector<sourcelocation, numberofompallocateclausemodifiers=""> + AllocClauseModifiersLoc; + Expr *AllocateAlignment = nullptr; }; OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind, @@ -1166,10 +1171,15 @@ class SemaOpenMP : public SemaBase { SourceLocation LParenLoc, SourceLocation EndLoc); /// Called on well-formed 'allocate' clause. - OMPClause *ActOnOpenMPAllocateClause( - Expr *Allocator, OpenMPAllocateClauseModifier ACModifier, - ArrayRef VarList, SourceLocation StartLoc, - SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + OMPClause * + ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, + OpenMPAllocateClauseModifier FirstModifier, + SourceLocation FirstModifierLoc, + OpenMPAllocateClauseModifier SecondModifier, + SourceLocation SecondModifierLoc, + ArrayRef VarList, SourceLocation StartLoc, + SourceLocation ColonLoc, SourceLocation LParenLoc, + SourceLocation EndLoc); /// Called on well-formed 'private' clause. OMPClause *ActOnOpenMPPrivateClause(ArrayRef VarList, SourceLocation StartLoc, diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 4246ba95d827f..532933d6183ce 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -1019,19 +1019,18 @@ OMPPartialClause *OMPPartialClause::CreateEmpty(const ASTContext &C) { return new (C) OMPPartialClause(); } -OMPAllocateClause * -OMPAllocateClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, Expr *Allocator, - SourceLocation ColonLoc, - OpenMPAllocateClauseModifier AllocatorModifier, - SourceLocation AllocatorModifierLoc, - SourceLocation EndLoc, ArrayRef VL) { +OMPAllocateClause *OMPAllocateClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, + OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, + OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, + SourceLocation EndLoc, ArrayRef VL) { // Allocate space for private variables and initializer expressions. void *Mem = C.Allocate(totalSizeToAlloc(VL.size())); auto *Clause = new (Mem) OMPAllocateClause( - StartLoc, LParenLoc, Allocator, ColonLoc, AllocatorModifier, - AllocatorModifierLoc, EndLoc, VL.size()); + StartLoc, LParenLoc, Allocator, Alignment, ColonLoc, Modifier1, + Modifier1Loc, Modifier2, Modifier2Loc, EndLoc, VL.size()); Clause->setVarRefs(VL); return Clause; @@ -2245,21 +2244,48 @@ void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) { void OMPClausePrinter::VisitOMPAllocateClause(OMPAllocateClause *Node) { if (Node->varlist_empty()) return; + + Expr *FirstModifier = nullptr; + Expr *SecondModifier = nullptr; + auto FirstAllocMod = Node->getFirstAllocateModifier(); + auto SecondAllocMod = Node->getSecondAllocateModifier(); + bool FirstUnknown = FirstAllocMod == OMPC_ALLOCATE_unknown; + bool SecondUnknown = SecondAllocMod == OMPC_ALLOCATE_unknown; + if (FirstAllocMod == OMPC_ALLOCATE_allocator || + (FirstAllocMod == OMPC_ALLOCATE_unknown && Node->getAllocator())) { + FirstModifier = Node->getAllocator(); + SecondModifier = Node->getAlignment(); + } else { + FirstModifier = Node->getAlignment(); + SecondModifier = Node->getAllocator(); + } + OS << "allocate"; - OpenMPAllocateClauseModifier Modifier = Node->getAllocatorModifier(); - if (Expr *Allocator = Node->getAllocator()) { + // If we have any explicit modifiers. + if (FirstModifier) { OS << "("; - if (Modifier == OMPC_ALLOCATE_allocator) { - OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier); + if (!FirstUnknown) { + OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), FirstAllocMod); OS << "("; - Allocator->printPretty(OS, nullptr, Policy, 0); + } + FirstModifier->printPretty(OS, nullptr, Policy, 0); + if (!FirstUnknown) OS << ")"; - } else { - Allocator->printPretty(OS, nullptr, Policy, 0); + if (SecondModifier) { + OS << ", "; + if (!SecondUnknown) { + OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), + SecondAllocMod); + OS << "("; + } + SecondModifier->printPretty(OS, nullptr, Policy, 0); + if (!SecondUnknown) + OS << ")"; } OS << ":"; VisitOMPClauseList(Node, ' '); } else { + // No modifiers. Just print the variable list. VisitOMPClauseList(Node, '('); } OS << ")"; diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index b4e973bc84a7b..89b83938f352d 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -4530,32 +4530,88 @@ static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, } /// Parse 'allocate' clause modifiers. -/// If allocator-modifier exists, return an expression for it and set -/// Data field noting modifier was specified. -/// +/// If allocator-modifier exists, return an expression for it. For both +/// allocator and align modifiers, set Data fields as appropriate. static ExprResult parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data) { const Token &Tok = P.getCurToken(); Preprocessor &PP = P.getPreprocessor(); ExprResult Tail; - auto Modifier = static_cast( + ExprResult Val; + SourceLocation RLoc; + bool AllocatorSeen = false; + bool AlignSeen = false; + SourceLocation CurrentModifierLoc = Tok.getLocation(); + auto CurrentModifier = static_cast( getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts())); - if (Modifier == OMPC_ALLOCATE_allocator) { - Data.AllocClauseModifier = Modifier; + + // Modifiers did not exist before 5.1 + if (P.getLangOpts().OpenMP < 51) + return P.ParseAssignmentExpression(); + + // An allocator-simple-modifier is exclusive and must appear alone. See + // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50, + // description of "exclusive" property. If we don't recognized an explicit + // simple-/complex- modifier, assume we're looking at expression + // representing allocator and consider ourselves done. + if (CurrentModifier == OMPC_ALLOCATE_unknown) + return P.ParseAssignmentExpression(); + + do { P.ConsumeToken(); - BalancedDelimiterTracker AllocateT(P, tok::l_paren, - tok::annot_pragma_openmp_end); if (Tok.is(tok::l_paren)) { - AllocateT.consumeOpen(); - Tail = P.ParseAssignmentExpression(); - AllocateT.consumeClose(); + switch (CurrentModifier) { + case OMPC_ALLOCATE_allocator: { + if (AllocatorSeen) { + P.Diag(Tok, diag::err_omp_duplicate_modifier) + << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier) + << getOpenMPClauseName(Kind); + } else { + Data.AllocClauseModifiers.push_back(CurrentModifier); + Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc); + } + BalancedDelimiterTracker AllocateT(P, tok::l_paren, + tok::annot_pragma_openmp_end); + AllocateT.consumeOpen(); + Tail = P.ParseAssignmentExpression(); + AllocateT.consumeClose(); + AllocatorSeen = true; + break; + } + case OMPC_ALLOCATE_align: { + if (AlignSeen) { + P.Diag(Tok, diag::err_omp_duplicate_modifier) + << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier) + << getOpenMPClauseName(Kind); + } else { + Data.AllocClauseModifiers.push_back(CurrentModifier); + Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc); + } + Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); + if (Val.isUsable()) + Data.AllocateAlignment = Val.get(); + AlignSeen = true; + break; + } + default: + llvm_unreachable("Unexpected allocate modifier"); + } } else { P.Diag(Tok, diag::err_expected) << tok::l_paren; } - } else { - Tail = P.ParseAssignmentExpression(); - } + if (Tok.isNot(tok::comma)) + break; + P.ConsumeToken(); + CurrentModifierLoc = Tok.getLocation(); + CurrentModifier = static_cast( + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts())); + // A modifier followed by a comma implies another modifier. + if (CurrentModifier == OMPC_ALLOCATE_unknown) { + P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind); + break; + } + } while (!AllocatorSeen || !AlignSeen); return Tail; } @@ -4832,7 +4888,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } else if (Kind == OMPC_allocate || (Kind == OMPC_affinity && Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator")) { - // Handle optional allocator expression followed by colon delimiter. + // Handle optional allocator and align modifiers followed by colon + // delimiter. ColonProtectionRAIIObject ColonRAII(*this); TentativeParsingAction TPA(*this); // OpenMP 5.0, 2.10.1, task Construct. @@ -4849,19 +4906,18 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Tail = Actions.CorrectDelayedTyposInExpr(Tail); Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), /*DiscardedValue=*/false); - if (Tail.isUsable()) { + if (Tail.isUsable() || Data.AllocateAlignment) { if (Tok.is(tok::colon)) { - Data.DepModOrTailExpr = Tail.get(); + Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr; Data.ColonLoc = ConsumeToken(); TPA.Commit(); } else { // Colon not found, parse only list of variables. TPA.Revert(); - if (Kind == OMPC_allocate && - Data.AllocClauseModifier == OMPC_ALLOCATE_allocator) { + if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) { SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); - Diag(Tok, diag::err_modifier_expected_colon) << "allocator"; + Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause"; } } } else { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 66ff92f554fc4..b83b2b12f4a23 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5320,6 +5320,8 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, Expr *SimpleRefExpr = E; auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange); ValueDecl *VD = Res.first; + if (!VD) + continue; DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false); if (!isOpenMPPrivate(Data.CKind)) { S.Diag(E->getExprLoc(), @@ -5330,10 +5332,8 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD, AllocatorKind, AC->getAllocator())) continue; - // Placeholder until allocate clause supports align modifier. - Expr *Alignment = nullptr; applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(), - Alignment, E->getSourceRange()); + AC->getAlignment(), E->getSourceRange()); } } } @@ -15617,7 +15617,9 @@ ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause( << E->getSourceRange(); return ExprError(); } - if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) { + if ((CKind == OMPC_aligned || CKind == OMPC_align || + CKind == OMPC_allocate) && + !Result.isPowerOf2()) { Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two) << E->getSourceRange(); return ExprError(); @@ -17153,11 +17155,26 @@ OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, case OMPC_has_device_addr: Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs); break; - case OMPC_allocate: - Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, - Data.AllocClauseModifier, VarList, StartLoc, - LParenLoc, ColonLoc, EndLoc); + case OMPC_allocate: { + OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown; + OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown; + SourceLocation Modifier1Loc, Modifier2Loc; + if (!Data.AllocClauseModifiers.empty()) { + assert(Data.AllocClauseModifiers.size() <= 2 && + "More allocate modifiers than expected"); + Modifier1 = Data.AllocClauseModifiers[0]; + Modifier1Loc = Data.AllocClauseModifiersLoc[0]; + if (Data.AllocClauseModifiers.size() == 2) { + Modifier2 = Data.AllocClauseModifiers[1]; + Modifier2Loc = Data.AllocClauseModifiersLoc[1]; + } + } + Res = ActOnOpenMPAllocateClause( + Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc, + Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc, + EndLoc); break; + } case OMPC_nontemporal: Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc); break; @@ -23163,32 +23180,37 @@ SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef VarList, } OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause( - Expr *Allocator, OpenMPAllocateClauseModifier AllocClauseModifier, - ArrayRef VarList, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ColonLoc, SourceLocation EndLoc) { - + Expr *Allocator, Expr *Alignment, + OpenMPAllocateClauseModifier FirstAllocateModifier, + SourceLocation FirstAllocateModifierLoc, + OpenMPAllocateClauseModifier SecondAllocateModifier, + SourceLocation SecondAllocateModifierLoc, ArrayRef VarList, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc) { if (Allocator) { // Allocator expression is dependent - skip it for now and build the // allocator when instantiated. - if (Allocator->isTypeDependent() || Allocator->isValueDependent() || - Allocator->isInstantiationDependent() || - Allocator->containsUnexpandedParameterPack()) - return nullptr; - // OpenMP [2.11.4 allocate Clause, Description] - // allocator is an expression of omp_allocator_handle_t type. - if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack)) - return nullptr; + bool AllocDependent = + (Allocator->isTypeDependent() || Allocator->isValueDependent() || + Allocator->isInstantiationDependent() || + Allocator->containsUnexpandedParameterPack()); + if (!AllocDependent) { + // OpenMP [2.11.4 allocate Clause, Description] + // allocator is an expression of omp_allocator_handle_t type. + if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack)) + return nullptr; - ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator); - if (AllocatorRes.isInvalid()) - return nullptr; - AllocatorRes = SemaRef.PerformImplicitConversion( - AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(), - AssignmentAction::Initializing, - /*AllowExplicit=*/true); - if (AllocatorRes.isInvalid()) - return nullptr; - Allocator = AllocatorRes.get(); + ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator); + if (AllocatorRes.isInvalid()) + return nullptr; + AllocatorRes = SemaRef.PerformImplicitConversion( + AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(), + AssignmentAction::Initializing, + /*AllowExplicit=*/true); + if (AllocatorRes.isInvalid()) + return nullptr; + Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr; + } } else { // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions. // allocate clauses that appear on a target construct or on constructs in a @@ -23199,6 +23221,17 @@ OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause( !DSAStack->hasRequiresDeclWithClause()) SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression); } + if (Alignment) { + bool AlignmentDependent = Alignment->isTypeDependent() || + Alignment->isValueDependent() || + Alignment->isInstantiationDependent() || + Alignment->containsUnexpandedParameterPack(); + if (!AlignmentDependent) { + ExprResult AlignResult = + VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate); + Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr; + } + } // Analyze and build list of variables. SmallVector Vars; for (Expr *RefExpr : VarList) { @@ -23230,11 +23263,10 @@ OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause( if (Allocator) DSAStack->addInnerAllocatorExpr(Allocator); - OpenMPAllocateClauseModifier AllocatorModifier = AllocClauseModifier; - SourceLocation AllocatorModifierLoc; - return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc, - Allocator, ColonLoc, AllocatorModifier, - AllocatorModifierLoc, EndLoc, Vars); + return OMPAllocateClause::Create( + getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc, + FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier, + SecondAllocateModifierLoc, EndLoc, Vars); } OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef VarList, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 4a3c739ecbeab..4fae2ccb5f6d0 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2075,15 +2075,18 @@ class TreeTransform { /// /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. - OMPClause *RebuildOMPAllocateClause(Expr *Allocate, - OpenMPAllocateClauseModifier ACModifier, - ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ColonLoc, - SourceLocation EndLoc) { + OMPClause * + RebuildOMPAllocateClause(Expr *Allocate, Expr *Alignment, + OpenMPAllocateClauseModifier FirstModifier, + SourceLocation FirstModifierLoc, + OpenMPAllocateClauseModifier SecondModifier, + SourceLocation SecondModifierLoc, + ArrayRef VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, + SourceLocation EndLoc) { return getSema().OpenMP().ActOnOpenMPAllocateClause( - Allocate, ACModifier, VarList, StartLoc, LParenLoc, ColonLoc, EndLoc); + Allocate, Alignment, FirstModifier, FirstModifierLoc, SecondModifier, + SecondModifierLoc, VarList, StartLoc, LParenLoc, ColonLoc, EndLoc); } /// Build a new OpenMP 'num_teams' clause. @@ -11224,6 +11227,13 @@ TreeTransform::TransformOMPAllocateClause(OMPAllocateClause *C) { return nullptr; Allocator = AllocatorRes.get(); } + Expr *Alignment = C->getAlignment(); + if (Alignment) { + ExprResult AlignmentRes = getDerived().TransformExpr(Alignment); + if (AlignmentRes.isInvalid()) + return nullptr; + Alignment = AlignmentRes.get(); + } llvm::SmallVector Vars; Vars.reserve(C->varlist_size()); for (auto *VE : C->varlist()) { @@ -11233,7 +11243,9 @@ TreeTransform::TransformOMPAllocateClause(OMPAllocateClause *C) { Vars.push_back(EVar.get()); } return getDerived().RebuildOMPAllocateClause( - Allocator, C->getAllocatorModifier(), Vars, C->getBeginLoc(), + Allocator, Alignment, C->getFirstAllocateModifier(), + C->getFirstAllocateModifierLoc(), C->getSecondAllocateModifier(), + C->getSecondAllocateModifierLoc(), Vars, C->getBeginLoc(), C->getLParenLoc(), C->getColonLoc(), C->getEndLoc()); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b53f99732cacc..7361cace49dd7 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11824,10 +11824,12 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) { } void OMPClauseReader::VisitOMPAllocateClause(OMPAllocateClause *C) { - C->setAllocatorModifier(Record.readEnum()); + C->setFirstAllocateModifier(Record.readEnum()); + C->setSecondAllocateModifier(Record.readEnum()); C->setLParenLoc(Record.readSourceLocation()); C->setColonLoc(Record.readSourceLocation()); C->setAllocator(Record.readSubExpr()); + C->setAlignment(Record.readSubExpr()); unsigned NumVars = C->varlist_size(); SmallVector Vars; Vars.reserve(NumVars); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 39004fd4d4c37..345d496a93312 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7924,10 +7924,12 @@ void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) { void OMPClauseWriter::VisitOMPAllocateClause(OMPAllocateClause *C) { Record.push_back(C->varlist_size()); - Record.writeEnum(C->getAllocatorModifier()); + Record.writeEnum(C->getFirstAllocateModifier()); + Record.writeEnum(C->getSecondAllocateModifier()); Record.AddSourceLocation(C->getLParenLoc()); Record.AddSourceLocation(C->getColonLoc()); Record.AddStmt(C->getAllocator()); + Record.AddStmt(C->getAlignment()); for (auto *VE : C->varlist()) Record.AddStmt(VE); } diff --git a/clang/test/OpenMP/allocate_allocator_modifier_codegen.cpp b/clang/test/OpenMP/allocate_allocator_modifier_codegen.cpp deleted file mode 100644 index 1bf927ebb2eb7..0000000000000 --- a/clang/test/OpenMP/allocate_allocator_modifier_codegen.cpp +++ /dev/null @@ -1,255 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --version 5 -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix CHECK-TLS %s - -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s -// expected-no-diagnostics - -#ifndef HEADER -#define HEADER - -enum omp_allocator_handle_t { - omp_null_allocator = 0, - omp_default_mem_alloc = 1, - omp_large_cap_mem_alloc = 2, - omp_const_mem_alloc = 3, - omp_high_bw_mem_alloc = 4, - omp_low_lat_mem_alloc = 5, - omp_cgroup_mem_alloc = 6, - omp_pteam_mem_alloc = 7, - omp_thread_mem_alloc = 8, - KMP_ALLOCATOR_MAX_HANDLE = __UINTPTR_MAX__ -}; - -template -struct ST { - static T m; -}; - -template T foo() { - T v; - #pragma omp scope private(v) allocate(allocator(TY):v) - v = ST::m; - return v; -} - -namespace ns { -int a; -} - -int main() { - static int a; - static int temp; - #pragma omp scope private(ns::a) allocate(allocator(omp_pteam_mem_alloc):ns::a) - ns::a++; - - #pragma omp scope private(a) allocate(allocator(omp_thread_mem_alloc):a) - a = 2; - double b = 3; - #pragma omp scope private(temp) allocate(temp) - temp += foo<int, omp_cgroup_mem_alloc="">(); - return temp+ns::a; -} - -extern template int ST::m; - -int b; - -void bar(int a, float &z) { - #pragma omp scope private(a,z) allocate(allocator(omp_default_mem_alloc):a,z) - a += b; -} -#endif -// CHECK-LABEL: define dso_local noundef i32 @main( -// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 -// CHECK-NEXT: [[B:%.*]] = alloca double, align 8 -// CHECK-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) -// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 -// CHECK-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 7 to ptr)) -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTA__VOID_ADDR]], align 4 -// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 -// CHECK-NEXT: store i32 [[INC]], ptr [[DOTA__VOID_ADDR]], align 4 -// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR]], ptr inttoptr (i64 7 to ptr)) -// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2:[0-9]+]], i32 [[TMP0]]) -// CHECK-NEXT: [[DOTA__VOID_ADDR1:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 8 to ptr)) -// CHECK-NEXT: store i32 2, ptr [[DOTA__VOID_ADDR1]], align 4 -// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR1]], ptr inttoptr (i64 8 to ptr)) -// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) -// CHECK-NEXT: store double 3.000000e+00, ptr [[B]], align 8 -// CHECK-NEXT: [[DOTTEMP__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr null) -// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_Z3fooIiL22omp_allocator_handle_t6EET_v() -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTTEMP__VOID_ADDR]], align 4 -// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP2]], [[CALL]] -// CHECK-NEXT: store i32 [[ADD]], ptr [[DOTTEMP__VOID_ADDR]], align 4 -// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTTEMP__VOID_ADDR]], ptr null) -// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) -// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr @_ZZ4mainE4temp, align 4 -// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr @_ZN2ns1aE, align 4 -// CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP3]], [[TMP4]] -// CHECK-NEXT: ret i32 [[ADD2]] -// -// -// CHECK-LABEL: define linkonce_odr noundef i32 @_Z3fooIiL22omp_allocator_handle_t6EET_v( -// CHECK-SAME: ) #[[ATTR3:[0-9]+]] comdat { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 -// CHECK-NEXT: [[V1:%.*]] = alloca i32, align 4 -// CHECK-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @_ZN2STIiE1mE, align 4 -// CHECK-NEXT: store i32 [[TMP1]], ptr [[V1]], align 4 -// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[V]], align 4 -// CHECK-NEXT: ret i32 [[TMP2]] -// -// -// CHECK-LABEL: define dso_local void @_Z3bariRf( -// CHECK-SAME: i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[Z:%.*]]) #[[ATTR3]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) -// CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 -// CHECK-NEXT: store ptr [[Z]], ptr [[Z_ADDR]], align 8 -// CHECK-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 1 to ptr)) -// CHECK-NEXT: [[DOTZ__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 1 to ptr)) -// CHECK-NEXT: store ptr [[DOTZ__VOID_ADDR]], ptr [[TMP]], align 8 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @b, align 4 -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTA__VOID_ADDR]], align 4 -// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP2]], [[TMP1]] -// CHECK-NEXT: store i32 [[ADD]], ptr [[DOTA__VOID_ADDR]], align 4 -// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTZ__VOID_ADDR]], ptr inttoptr (i64 1 to ptr)) -// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR]], ptr inttoptr (i64 1 to ptr)) -// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) -// CHECK-NEXT: ret void -// -// -// CHECK-TLS-LABEL: define dso_local noundef i32 @main( -// CHECK-TLS-SAME: ) #[[ATTR0:[0-9]+]] { -// CHECK-TLS-NEXT: [[ENTRY:.*:]] -// CHECK-TLS-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 -// CHECK-TLS-NEXT: [[B:%.*]] = alloca double, align 8 -// CHECK-TLS-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) -// CHECK-TLS-NEXT: store i32 0, ptr [[RETVAL]], align 4 -// CHECK-TLS-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 7 to ptr)) -// CHECK-TLS-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTA__VOID_ADDR]], align 4 -// CHECK-TLS-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 -// CHECK-TLS-NEXT: store i32 [[INC]], ptr [[DOTA__VOID_ADDR]], align 4 -// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR]], ptr inttoptr (i64 7 to ptr)) -// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2:[0-9]+]], i32 [[TMP0]]) -// CHECK-TLS-NEXT: [[DOTA__VOID_ADDR1:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 8 to ptr)) -// CHECK-TLS-NEXT: store i32 2, ptr [[DOTA__VOID_ADDR1]], align 4 -// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR1]], ptr inttoptr (i64 8 to ptr)) -// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) -// CHECK-TLS-NEXT: store double 3.000000e+00, ptr [[B]], align 8 -// CHECK-TLS-NEXT: [[DOTTEMP__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr null) -// CHECK-TLS-NEXT: [[CALL:%.*]] = call noundef i32 @_Z3fooIiL22omp_allocator_handle_t6EET_v() -// CHECK-TLS-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTTEMP__VOID_ADDR]], align 4 -// CHECK-TLS-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP2]], [[CALL]] -// CHECK-TLS-NEXT: store i32 [[ADD]], ptr [[DOTTEMP__VOID_ADDR]], align 4 -// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTTEMP__VOID_ADDR]], ptr null) -// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) -// CHECK-TLS-NEXT: [[TMP3:%.*]] = load i32, ptr @_ZZ4mainE4temp, align 4 -// CHECK-TLS-NEXT: [[TMP4:%.*]] = load i32, ptr @_ZN2ns1aE, align 4 -// CHECK-TLS-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP3]], [[TMP4]] -// CHECK-TLS-NEXT: ret i32 [[ADD2]] -// -// -// CHECK-TLS-LABEL: define linkonce_odr noundef i32 @_Z3fooIiL22omp_allocator_handle_t6EET_v( -// CHECK-TLS-SAME: ) #[[ATTR3:[0-9]+]] comdat { -// CHECK-TLS-NEXT: [[ENTRY:.*:]] -// CHECK-TLS-NEXT: [[V:%.*]] = alloca i32, align 4 -// CHECK-TLS-NEXT: [[V1:%.*]] = alloca i32, align 4 -// CHECK-TLS-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) -// CHECK-TLS-NEXT: [[TMP1:%.*]] = load i32, ptr @_ZN2STIiE1mE, align 4 -// CHECK-TLS-NEXT: store i32 [[TMP1]], ptr [[V1]], align 4 -// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) -// CHECK-TLS-NEXT: [[TMP2:%.*]] = load i32, ptr [[V]], align 4 -// CHECK-TLS-NEXT: ret i32 [[TMP2]] -// -// -// CHECK-TLS-LABEL: define dso_local void @_Z3bariRf( -// CHECK-TLS-SAME: i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[Z:%.*]]) #[[ATTR3]] { -// CHECK-TLS-NEXT: [[ENTRY:.*:]] -// CHECK-TLS-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-TLS-NEXT: [[Z_ADDR:%.*]] = alloca ptr, align 8 -// CHECK-TLS-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// CHECK-TLS-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) -// CHECK-TLS-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 -// CHECK-TLS-NEXT: store ptr [[Z]], ptr [[Z_ADDR]], align 8 -// CHECK-TLS-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 1 to ptr)) -// CHECK-TLS-NEXT: [[DOTZ__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 1 to ptr)) -// CHECK-TLS-NEXT: store ptr [[DOTZ__VOID_ADDR]], ptr [[TMP]], align 8 -// CHECK-TLS-NEXT: [[TMP1:%.*]] = load i32, ptr @b, align 4 -// CHECK-TLS-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTA__VOID_ADDR]], align 4 -// CHECK-TLS-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP2]], [[TMP1]] -// CHECK-TLS-NEXT: store i32 [[ADD]], ptr [[DOTA__VOID_ADDR]], align 4 -// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTZ__VOID_ADDR]], ptr inttoptr (i64 1 to ptr)) -// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR]], ptr inttoptr (i64 1 to ptr)) -// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) -// CHECK-TLS-NEXT: ret void -// -// -// SIMD-ONLY0-LABEL: define dso_local noundef i32 @main( -// SIMD-ONLY0-SAME: ) #[[ATTR0:[0-9]+]] { -// SIMD-ONLY0-NEXT: [[ENTRY:.*:]] -// SIMD-ONLY0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 -// SIMD-ONLY0-NEXT: [[A:%.*]] = alloca i32, align 4 -// SIMD-ONLY0-NEXT: [[A1:%.*]] = alloca i32, align 4 -// SIMD-ONLY0-NEXT: [[B:%.*]] = alloca double, align 8 -// SIMD-ONLY0-NEXT: [[TEMP:%.*]] = alloca i32, align 4 -// SIMD-ONLY0-NEXT: store i32 0, ptr [[RETVAL]], align 4 -// SIMD-ONLY0-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4 -// SIMD-ONLY0-NEXT: [[INC:%.*]] = add nsw i32 [[TMP0]], 1 -// SIMD-ONLY0-NEXT: store i32 [[INC]], ptr [[A]], align 4 -// SIMD-ONLY0-NEXT: store i32 2, ptr [[A1]], align 4 -// SIMD-ONLY0-NEXT: store double 3.000000e+00, ptr [[B]], align 8 -// SIMD-ONLY0-NEXT: [[CALL:%.*]] = call noundef i32 @_Z3fooIiL22omp_allocator_handle_t6EET_v() -// SIMD-ONLY0-NEXT: [[TMP1:%.*]] = load i32, ptr [[TEMP]], align 4 -// SIMD-ONLY0-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP1]], [[CALL]] -// SIMD-ONLY0-NEXT: store i32 [[ADD]], ptr [[TEMP]], align 4 -// SIMD-ONLY0-NEXT: [[TMP2:%.*]] = load i32, ptr @_ZZ4mainE4temp, align 4 -// SIMD-ONLY0-NEXT: [[TMP3:%.*]] = load i32, ptr @_ZN2ns1aE, align 4 -// SIMD-ONLY0-NEXT: [[ADD2:%.*]] = add nsw i32 [[TMP2]], [[TMP3]] -// SIMD-ONLY0-NEXT: ret i32 [[ADD2]] -// -// -// SIMD-ONLY0-LABEL: define linkonce_odr noundef i32 @_Z3fooIiL22omp_allocator_handle_t6EET_v( -// SIMD-ONLY0-SAME: ) #[[ATTR1:[0-9]+]] comdat { -// SIMD-ONLY0-NEXT: [[ENTRY:.*:]] -// SIMD-ONLY0-NEXT: [[V:%.*]] = alloca i32, align 4 -// SIMD-ONLY0-NEXT: [[V1:%.*]] = alloca i32, align 4 -// SIMD-ONLY0-NEXT: [[TMP0:%.*]] = load i32, ptr @_ZN2STIiE1mE, align 4 -// SIMD-ONLY0-NEXT: store i32 [[TMP0]], ptr [[V1]], align 4 -// SIMD-ONLY0-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 -// SIMD-ONLY0-NEXT: ret i32 [[TMP1]] -// -// -// SIMD-ONLY0-LABEL: define dso_local void @_Z3bariRf( -// SIMD-ONLY0-SAME: i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[Z:%.*]]) #[[ATTR1]] { -// SIMD-ONLY0-NEXT: [[ENTRY:.*:]] -// SIMD-ONLY0-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// SIMD-ONLY0-NEXT: [[Z_ADDR:%.*]] = alloca ptr, align 8 -// SIMD-ONLY0-NEXT: [[A1:%.*]] = alloca i32, align 4 -// SIMD-ONLY0-NEXT: [[Z2:%.*]] = alloca float, align 4 -// SIMD-ONLY0-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -// SIMD-ONLY0-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 -// SIMD-ONLY0-NEXT: store ptr [[Z]], ptr [[Z_ADDR]], align 8 -// SIMD-ONLY0-NEXT: store ptr [[Z2]], ptr [[TMP]], align 8 -// SIMD-ONLY0-NEXT: [[TMP0:%.*]] = load i32, ptr @b, align 4 -// SIMD-ONLY0-NEXT: [[TMP1:%.*]] = load i32, ptr [[A1]], align 4 -// SIMD-ONLY0-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP1]], [[TMP0]] -// SIMD-ONLY0-NEXT: store i32 [[ADD]], ptr [[A1]], align 4 -// SIMD-ONLY0-NEXT: ret void -// diff --git a/clang/test/OpenMP/allocate_allocator_modifier_messages.cpp b/clang/test/OpenMP/allocate_allocator_modifier_messages.cpp deleted file mode 100644 index 160c4996c1219..0000000000000 --- a/clang/test/OpenMP/allocate_allocator_modifier_messages.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 %s - -typedef enum omp_allocator_handle_t { - omp_null_allocator = 0, - omp_default_mem_alloc = 1, - omp_large_cap_mem_alloc = 2, - omp_const_mem_alloc = 3, - omp_high_bw_mem_alloc = 4, - omp_low_lat_mem_alloc = 5, - omp_cgroup_mem_alloc = 6, - omp_pteam_mem_alloc = 7, - omp_thread_mem_alloc = 8, -} omp_allocator_handle_t; - -int myAlloc() { - return 100; -} - -int main() { - int a, b, c; - // expected-error@+4 {{expected '('}} - // expected-error@+3 {{expected expression}} - // expected-error@+2 {{expected ')'}} - // expected-note@+1 {{to match this '('}} - #pragma omp scope private(c) allocate(allocator - // expected-error@+6 {{expected expression}} - // expected-error@+5 {{expected ')'}} - // expected-note@+4 {{to match this '('}} - // expected-error@+3 {{expected expression}} - // expected-error@+2 {{expected ')'}} - // expected-note@+1 {{to match this '('}} - #pragma omp scope private(c) allocate(allocator( - // expected-error@+4 {{expected expression}} - // expected-error@+3 {{expected expression}} - // expected-error@+2 {{expected ')'}} - // expected-note@+1 {{to match this '('}} - #pragma omp scope private(c) allocate(allocator() - // expected-error@+2 {{expected expression}} - // expected-error@+1 {{expected expression}} - #pragma omp scope private(c) allocate(allocator()) - // expected-error@+6 {{expected ')'}} - // expected-note@+5 {{to match this '('}} - // expected-error@+4 {{missing ':' after allocator modifier}} - // expected-error@+3 {{expected expression}} - // expected-error@+2 {{expected ')'}} - // expected-note@+1 {{to match this '('}} - #pragma omp scope private(c) allocate(allocator(omp_default_mem_alloc - // expected-error@+6 {{missing ':' after allocator modifier}} - // expected-error@+5 {{expected expression}} - // expected-error@+4 {{expected ')'}} - // expected-note@+3 {{to match this '('}} - // expected-error@+2 {{expected ')'}} - // expected-note@+1 {{to match this '('}} - #pragma omp scope private(c) allocate(allocator(omp_large_cap_mem_alloc: - // expected-error@+4 {{missing ':' after allocator modifier}} - // expected-error@+3 {{expected expression}} - // expected-error@+2 {{expected ')'}} - // expected-note@+1 {{to match this '('}} - #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc) - // expected-error@+2 {{missing ':' after allocator modifier}} - // expected-error@+1 {{expected expression}} - #pragma omp scope private(c) allocate(allocator(omp_high_bw_mem_alloc)) - // expected-error@+1 {{expected expression}} - #pragma omp scope private(c) allocate(allocator(omp_low_lat_mem_alloc):) - // expected-error@+6 {{expected ')'}} - // expected-note@+5 {{to match this '('}} - // expected-error@+4 {{missing ':' after allocator modifier}} - // expected-error@+3 {{expected expression}} - // expected-error@+2 {{expected ')'}} - // expected-note@+1 {{to match this '('}} - #pragma omp scope private(c) allocate(allocator(omp_cgroup_mem_alloc:) - // expected-error@+4 {{expected ')'}} - // expected-note@+3 {{to match this '('}} - // expected-error@+2 {{missing ':' after allocator modifier}} - // expected-error@+1 {{expected expression}} - #pragma omp scope private(c) allocate(allocator(omp_pteam_mem_alloc:)) - // expected-error@+4 {{expected ')'}} - // expected-note@+3 {{to match this '('}} - // expected-error@+2 {{missing ':' after allocator modifier}} - // expected-error@+1 {{expected expression}} - #pragma omp scope private(c) allocate(allocator(omp_thread_mem_alloc:c)) - // expected-error@+1 {{expected variable name}} - #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc):1) - // expected-error@+1 {{expected variable name}} - #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc):-10) - // expected-error@+4 {{expected ',' or ')' in 'allocate' clause}} - // expected-error@+3 {{expected ')'}} - // expected-warning@+2 {{extra tokens at the end of '#pragma omp scope' are ignored}} - // expected-note@+1 {{to match this '('}} - #pragma omp scope private(a,b,c) allocate(allocator(omp_const_mem_alloc):c:b;a) - // expected-error@+1 {{initializing 'const omp_allocator_handle_t' with an expression of incompatible type 'int'}} - #pragma omp scope private(c,a,b) allocate(allocator(myAlloc()):a,b,c) - // expected-error@+2 {{missing ':' after allocator modifier}} - // expected-error@+1 {{expected expression}} - #pragma omp scope private(c) allocate(allocator(omp_default_mem_alloc);c) - ++a; -} diff --git a/clang/test/OpenMP/allocate_allocator_modifier_ast_print.cpp b/clang/test/OpenMP/allocate_modifiers_ast_print.cpp similarity index 51% rename from clang/test/OpenMP/allocate_allocator_modifier_ast_print.cpp rename to clang/test/OpenMP/allocate_modifiers_ast_print.cpp index 15f3f1dd9bbb9..436647be75da3 100644 --- a/clang/test/OpenMP/allocate_allocator_modifier_ast_print.cpp +++ b/clang/test/OpenMP/allocate_modifiers_ast_print.cpp @@ -41,6 +41,11 @@ int main() { #pragma omp scope private(c,a,b) allocate(allocator(myAlloc()):a,b,c) c++; #pragma omp scope private(c,a,b,d) allocate(myAlloc():a,b,c,d) + a++; + #pragma omp scope private(a,b) allocate(align(2), allocator(omp_const_mem_alloc):a,b) + b++; + #pragma omp scope private(c,a,b) allocate(allocator(myAlloc()), align(8) :a,b,c) + c++; // DUMP: FunctionDecl {{.*}} // DUMP: DeclRefExpr {{.*}}'omp_allocator_handle_t' EnumConstant {{.*}}'omp_large_cap_mem_alloc' 'omp_allocator_handle_t' // DUMP: FunctionDecl {{.*}} @@ -76,11 +81,81 @@ int main() { // DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'b' 'int' // DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'c' 'int' // DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'d' 'int' +// DUMP: OMPScopeDirective {{.*}} +// DUMP: OMPPrivateClause {{.*}} +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'a' 'int' +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'b' 'int' +// DUMP: OMPAllocateClause {{.*}} +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'a' 'int' +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'b' 'int' +// DUMP: OMPScopeDirective {{.*}} +// DUMP: OMPPrivateClause {{.*}} +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'c' 'int' +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'a' 'int' +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'b' 'int' +// DUMP: OMPAllocateClause {{.*}} +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'a' 'int' +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'b' 'int' +// DUMP: DeclRefExpr {{.*}}'int' lvalue Var {{.*}}'c' 'int' // PRINT: #pragma omp scope private(a) allocate(omp_const_mem_alloc: a) // PRINT: #pragma omp scope private(a,b) allocate(allocator(omp_const_mem_alloc): a,b) // PRINT: #pragma omp scope private(c,a,b) allocate(allocator(myAlloc()): a,b,c) // PRINT: #pragma omp scope private(c,a,b,d) allocate(myAlloc(): a,b,c,d) - d++; +// PRINT: #pragma omp scope private(a,b) allocate(align(2), allocator(omp_const_mem_alloc): a,b) +// PRINT: #pragma omp scope private(c,a,b) allocate(allocator(myAlloc()), align(8): a,b,c) return a+b+c+d; } + +template+void templated_func(T n) { + int a, b; + T mem = n; + #pragma omp scope private(mem,a,b) allocate(allocator(n),align(al):mem,a,b) + a += b; + #pragma omp scope allocate(allocator(n),align(al):mem,a,b) private(mem,a,b) + a += b; +} + +void template_inst(int n) { + templated_func<omp_allocator_handle_t, 4="">(omp_const_mem_alloc); + return; +} +// DUMP: FunctionTemplateDecl{{.*}}templated_func +// DUMP: FunctionDecl{{.*}}templated_func 'void (T)' +// DUMP: OMPScopeDirective +// DUMP: OMPPrivateClause +// DUMP: OMPAllocateClause +// DUMP: DeclRefExpr{{.*}}'T' lvalue Var{{.*}}'mem' 'T' +// DUMP: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'a' 'int' +// DUMP: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'b' 'int' +// DUMP: OMPScopeDirective +// DUMP: OMPAllocateClause +// DUMP: DeclRefExpr{{.*}}'T' lvalue Var{{.*}}'mem' 'T' +// DUMP: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'a' 'int' +// DUMP: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'b' 'int' +// DUMP: OMPPrivateClause + +// DUMP: FunctionDecl{{.*}}used templated_func 'void (omp_allocator_handle_t)' implicit_instantiation +// DUMP: TemplateArgument type 'omp_allocator_handle_t' +// DUMP: EnumType{{.*}}'omp_allocator_handle_t' +// DUMP: Enum{{.*}}'omp_allocator_handle_t' +// DUMP: TemplateArgument integral '4U' + +// DUMP: OMPScopeDirective +// DUMP: OMPPrivateClause +// DUMP: OMPAllocateClause +// DUMP: DeclRefExpr{{.*}}'omp_allocator_handle_t' lvalue Var{{.*}}'mem' 'omp_allocator_handle_t' +// DUMP: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'a' 'int' +// DUMP: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'b' 'int' +// DUMP: OMPScopeDirective +// DUMP: OMPAllocateClause +// DUMP: DeclRefExpr{{.*}}'omp_allocator_handle_t' lvalue Var{{.*}}'mem' 'omp_allocator_handle_t' +// DUMP: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'a' 'int' +// DUMP: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'b' 'int' +// DUMP: OMPPrivateClause +// PRINT: #pragma omp scope private(mem,a,b) allocate(allocator(n), align(al): mem,a,b) +// PRINT: #pragma omp scope allocate(allocator(n), align(al): mem,a,b) private(mem,a,b) +// PRINT: #pragma omp scope private(mem,a,b) allocate(allocator(n), align(4U): mem,a,b) +// PRINT: #pragma omp scope allocate(allocator(n), align(4U): mem,a,b) private(mem,a,b) + #endif diff --git a/clang/test/OpenMP/allocate_modifiers_codegen.cpp b/clang/test/OpenMP/allocate_modifiers_codegen.cpp new file mode 100644 index 0000000000000..d798e9b3435f0 --- /dev/null +++ b/clang/test/OpenMP/allocate_modifiers_codegen.cpp @@ -0,0 +1,409 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --version 5 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix CHECK-TLS %s + +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=52 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix SIMD-ONLY0 %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=52 -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +enum omp_allocator_handle_t { + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + KMP_ALLOCATOR_MAX_HANDLE = __UINTPTR_MAX__ +}; + +template +struct ST { + static T m; +}; + +template T foo() { + T v; + #pragma omp scope private(v) allocate(allocator(TY):v) + v = ST::m; + #pragma omp scope private(v) allocate(align(al), allocator(TY):v) + ++v; + return v; +} + +namespace ns { +int a; +} + +omp_allocator_handle_t foo(); + +int main() { + static int a; + static int temp; + int v; + #pragma omp scope private(ns::a) allocate(allocator(omp_pteam_mem_alloc):ns::a) + ns::a++; + #pragma omp scope private(a) allocate(align(8),allocator(omp_thread_mem_alloc):a) + a = 2; + #pragma omp scope private(v) allocate(align(1) : v) + ++v; + #pragma omp scope private(v) allocate(allocator(omp_default_mem_alloc) : v) + ++v; + #pragma omp scope private(v) allocate(allocator(omp_large_cap_mem_alloc), align(8) : v) + ++v; + #pragma omp scope private(v) allocate(align(4) : v) + ++v; + #pragma omp scope private(v) allocate(align(2), allocator(omp_default_mem_alloc) : v) + ++v; + #pragma omp scope private(v) allocate(align(8), allocator(foo()) : v) + ++v; + + double b = 3; + #pragma omp scope private(temp) allocate(temp) + temp += foo<int, 8="" omp_cgroup_mem_alloc,="">(); + return temp+ns::a; +} + +extern template int ST::m; + +const int b = 8; + +void bar(int a, float &z) { + #pragma omp scope private(a,z) allocate(align(b), allocator(omp_default_mem_alloc) : a,z) + a += b + z; +} +#endif +// CHECK-LABEL: define dso_local noundef i32 @main( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[B:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) +// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 7 to ptr)) +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTA__VOID_ADDR]], align 4 +// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 +// CHECK-NEXT: store i32 [[INC]], ptr [[DOTA__VOID_ADDR]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR]], ptr inttoptr (i64 7 to ptr)) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2:[0-9]+]], i32 [[TMP0]]) +// CHECK-NEXT: [[DOTA__VOID_ADDR1:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 8 to ptr)) +// CHECK-NEXT: store i32 2, ptr [[DOTA__VOID_ADDR1]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR1]], ptr inttoptr (i64 8 to ptr)) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[DOTV__VOID_ADDR:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 4, i64 4, ptr null) +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTV__VOID_ADDR]], align 4 +// CHECK-NEXT: [[INC2:%.*]] = add nsw i32 [[TMP2]], 1 +// CHECK-NEXT: store i32 [[INC2]], ptr [[DOTV__VOID_ADDR]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR]], ptr null) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[DOTV__VOID_ADDR3:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 1 to ptr)) +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTV__VOID_ADDR3]], align 4 +// CHECK-NEXT: [[INC4:%.*]] = add nsw i32 [[TMP3]], 1 +// CHECK-NEXT: store i32 [[INC4]], ptr [[DOTV__VOID_ADDR3]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR3]], ptr inttoptr (i64 1 to ptr)) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[DOTV__VOID_ADDR5:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 2 to ptr)) +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTV__VOID_ADDR5]], align 4 +// CHECK-NEXT: [[INC6:%.*]] = add nsw i32 [[TMP4]], 1 +// CHECK-NEXT: store i32 [[INC6]], ptr [[DOTV__VOID_ADDR5]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR5]], ptr inttoptr (i64 2 to ptr)) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[DOTV__VOID_ADDR7:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 4, i64 4, ptr null) +// CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTV__VOID_ADDR7]], align 4 +// CHECK-NEXT: [[INC8:%.*]] = add nsw i32 [[TMP5]], 1 +// CHECK-NEXT: store i32 [[INC8]], ptr [[DOTV__VOID_ADDR7]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR7]], ptr null) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[DOTV__VOID_ADDR9:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 4, i64 4, ptr inttoptr (i64 1 to ptr)) +// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTV__VOID_ADDR9]], align 4 +// CHECK-NEXT: [[INC10:%.*]] = add nsw i32 [[TMP6]], 1 +// CHECK-NEXT: store i32 [[INC10]], ptr [[DOTV__VOID_ADDR9]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR9]], ptr inttoptr (i64 1 to ptr)) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[CALL:%.*]] = call noundef i64 @_Z3foov() +// CHECK-NEXT: [[CONV:%.*]] = inttoptr i64 [[CALL]] to ptr +// CHECK-NEXT: [[DOTV__VOID_ADDR11:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr [[CONV]]) +// CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTV__VOID_ADDR11]], align 4 +// CHECK-NEXT: [[INC12:%.*]] = add nsw i32 [[TMP7]], 1 +// CHECK-NEXT: store i32 [[INC12]], ptr [[DOTV__VOID_ADDR11]], align 4 +// CHECK-NEXT: [[CALL13:%.*]] = call noundef i64 @_Z3foov() +// CHECK-NEXT: [[CONV14:%.*]] = inttoptr i64 [[CALL13]] to ptr +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR11]], ptr [[CONV14]]) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: store double 3.000000e+00, ptr [[B]], align 8 +// CHECK-NEXT: [[DOTTEMP__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr null) +// CHECK-NEXT: [[CALL15:%.*]] = call noundef i32 @_Z3fooIiL22omp_allocator_handle_t6ELj8EET_v() +// CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTTEMP__VOID_ADDR]], align 4 +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP8]], [[CALL15]] +// CHECK-NEXT: store i32 [[ADD]], ptr [[DOTTEMP__VOID_ADDR]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTTEMP__VOID_ADDR]], ptr null) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr @_ZZ4mainE4temp, align 4 +// CHECK-NEXT: [[TMP10:%.*]] = load i32, ptr @_ZN2ns1aE, align 4 +// CHECK-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] +// CHECK-NEXT: ret i32 [[ADD16]] +// +// +// CHECK-LABEL: define linkonce_odr noundef i32 @_Z3fooIiL22omp_allocator_handle_t6ELj8EET_v( +// CHECK-SAME: ) #[[ATTR4:[0-9]+]] comdat { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) +// CHECK-NEXT: [[DOTV__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 6 to ptr)) +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @_ZN2STIiE1mE, align 4 +// CHECK-NEXT: store i32 [[TMP1]], ptr [[DOTV__VOID_ADDR]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR]], ptr inttoptr (i64 6 to ptr)) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[DOTV__VOID_ADDR1:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 6 to ptr)) +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTV__VOID_ADDR1]], align 4 +// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 +// CHECK-NEXT: store i32 [[INC]], ptr [[DOTV__VOID_ADDR1]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR1]], ptr inttoptr (i64 6 to ptr)) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[V]], align 4 +// CHECK-NEXT: ret i32 [[TMP3]] +// +// +// CHECK-LABEL: define dso_local void @_Z3bariRf( +// CHECK-SAME: i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[Z:%.*]]) #[[ATTR4]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) +// CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store ptr [[Z]], ptr [[Z_ADDR]], align 8 +// CHECK-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 1 to ptr)) +// CHECK-NEXT: [[DOTZ__VOID_ADDR:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 1 to ptr)) +// CHECK-NEXT: store ptr [[DOTZ__VOID_ADDR]], ptr [[TMP]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load float, ptr [[TMP1]], align 4 +// CHECK-NEXT: [[ADD:%.*]] = fadd float 8.000000e+00, [[TMP2]] +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTA__VOID_ADDR]], align 4 +// CHECK-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP3]] to float +// CHECK-NEXT: [[ADD1:%.*]] = fadd float [[CONV]], [[ADD]] +// CHECK-NEXT: [[CONV2:%.*]] = fptosi float [[ADD1]] to i32 +// CHECK-NEXT: store i32 [[CONV2]], ptr [[DOTA__VOID_ADDR]], align 4 +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTZ__VOID_ADDR]], ptr inttoptr (i64 1 to ptr)) +// CHECK-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR]], ptr inttoptr (i64 1 to ptr)) +// CHECK-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-NEXT: ret void +// +// +// CHECK-TLS-LABEL: define dso_local noundef i32 @main( +// CHECK-TLS-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-TLS-NEXT: [[ENTRY:.*:]] +// CHECK-TLS-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-TLS-NEXT: [[V:%.*]] = alloca i32, align 4 +// CHECK-TLS-NEXT: [[B:%.*]] = alloca double, align 8 +// CHECK-TLS-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) +// CHECK-TLS-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-TLS-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 7 to ptr)) +// CHECK-TLS-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTA__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 +// CHECK-TLS-NEXT: store i32 [[INC]], ptr [[DOTA__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR]], ptr inttoptr (i64 7 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2:[0-9]+]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[DOTA__VOID_ADDR1:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 8 to ptr)) +// CHECK-TLS-NEXT: store i32 2, ptr [[DOTA__VOID_ADDR1]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR1]], ptr inttoptr (i64 8 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[DOTV__VOID_ADDR:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 4, i64 4, ptr null) +// CHECK-TLS-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTV__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: [[INC2:%.*]] = add nsw i32 [[TMP2]], 1 +// CHECK-TLS-NEXT: store i32 [[INC2]], ptr [[DOTV__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR]], ptr null) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[DOTV__VOID_ADDR3:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 1 to ptr)) +// CHECK-TLS-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTV__VOID_ADDR3]], align 4 +// CHECK-TLS-NEXT: [[INC4:%.*]] = add nsw i32 [[TMP3]], 1 +// CHECK-TLS-NEXT: store i32 [[INC4]], ptr [[DOTV__VOID_ADDR3]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR3]], ptr inttoptr (i64 1 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[DOTV__VOID_ADDR5:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 2 to ptr)) +// CHECK-TLS-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTV__VOID_ADDR5]], align 4 +// CHECK-TLS-NEXT: [[INC6:%.*]] = add nsw i32 [[TMP4]], 1 +// CHECK-TLS-NEXT: store i32 [[INC6]], ptr [[DOTV__VOID_ADDR5]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR5]], ptr inttoptr (i64 2 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[DOTV__VOID_ADDR7:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 4, i64 4, ptr null) +// CHECK-TLS-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTV__VOID_ADDR7]], align 4 +// CHECK-TLS-NEXT: [[INC8:%.*]] = add nsw i32 [[TMP5]], 1 +// CHECK-TLS-NEXT: store i32 [[INC8]], ptr [[DOTV__VOID_ADDR7]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR7]], ptr null) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[DOTV__VOID_ADDR9:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 4, i64 4, ptr inttoptr (i64 1 to ptr)) +// CHECK-TLS-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTV__VOID_ADDR9]], align 4 +// CHECK-TLS-NEXT: [[INC10:%.*]] = add nsw i32 [[TMP6]], 1 +// CHECK-TLS-NEXT: store i32 [[INC10]], ptr [[DOTV__VOID_ADDR9]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR9]], ptr inttoptr (i64 1 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[CALL:%.*]] = call noundef i64 @_Z3foov() +// CHECK-TLS-NEXT: [[CONV:%.*]] = inttoptr i64 [[CALL]] to ptr +// CHECK-TLS-NEXT: [[DOTV__VOID_ADDR11:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr [[CONV]]) +// CHECK-TLS-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTV__VOID_ADDR11]], align 4 +// CHECK-TLS-NEXT: [[INC12:%.*]] = add nsw i32 [[TMP7]], 1 +// CHECK-TLS-NEXT: store i32 [[INC12]], ptr [[DOTV__VOID_ADDR11]], align 4 +// CHECK-TLS-NEXT: [[CALL13:%.*]] = call noundef i64 @_Z3foov() +// CHECK-TLS-NEXT: [[CONV14:%.*]] = inttoptr i64 [[CALL13]] to ptr +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR11]], ptr [[CONV14]]) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: store double 3.000000e+00, ptr [[B]], align 8 +// CHECK-TLS-NEXT: [[DOTTEMP__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr null) +// CHECK-TLS-NEXT: [[CALL15:%.*]] = call noundef i32 @_Z3fooIiL22omp_allocator_handle_t6ELj8EET_v() +// CHECK-TLS-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTTEMP__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP8]], [[CALL15]] +// CHECK-TLS-NEXT: store i32 [[ADD]], ptr [[DOTTEMP__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTTEMP__VOID_ADDR]], ptr null) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[TMP9:%.*]] = load i32, ptr @_ZZ4mainE4temp, align 4 +// CHECK-TLS-NEXT: [[TMP10:%.*]] = load i32, ptr @_ZN2ns1aE, align 4 +// CHECK-TLS-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP9]], [[TMP10]] +// CHECK-TLS-NEXT: ret i32 [[ADD16]] +// +// +// CHECK-TLS-LABEL: define linkonce_odr noundef i32 @_Z3fooIiL22omp_allocator_handle_t6ELj8EET_v( +// CHECK-TLS-SAME: ) #[[ATTR4:[0-9]+]] comdat { +// CHECK-TLS-NEXT: [[ENTRY:.*:]] +// CHECK-TLS-NEXT: [[V:%.*]] = alloca i32, align 4 +// CHECK-TLS-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) +// CHECK-TLS-NEXT: [[DOTV__VOID_ADDR:%.*]] = call ptr @__kmpc_alloc(i32 [[TMP0]], i64 4, ptr inttoptr (i64 6 to ptr)) +// CHECK-TLS-NEXT: [[TMP1:%.*]] = load i32, ptr @_ZN2STIiE1mE, align 4 +// CHECK-TLS-NEXT: store i32 [[TMP1]], ptr [[DOTV__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR]], ptr inttoptr (i64 6 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[DOTV__VOID_ADDR1:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 6 to ptr)) +// CHECK-TLS-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTV__VOID_ADDR1]], align 4 +// CHECK-TLS-NEXT: [[INC:%.*]] = add nsw i32 [[TMP2]], 1 +// CHECK-TLS-NEXT: store i32 [[INC]], ptr [[DOTV__VOID_ADDR1]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTV__VOID_ADDR1]], ptr inttoptr (i64 6 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: [[TMP3:%.*]] = load i32, ptr [[V]], align 4 +// CHECK-TLS-NEXT: ret i32 [[TMP3]] +// +// +// CHECK-TLS-LABEL: define dso_local void @_Z3bariRf( +// CHECK-TLS-SAME: i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[Z:%.*]]) #[[ATTR4]] { +// CHECK-TLS-NEXT: [[ENTRY:.*:]] +// CHECK-TLS-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-TLS-NEXT: [[Z_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-TLS-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// CHECK-TLS-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1]]) +// CHECK-TLS-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// CHECK-TLS-NEXT: store ptr [[Z]], ptr [[Z_ADDR]], align 8 +// CHECK-TLS-NEXT: [[DOTA__VOID_ADDR:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 1 to ptr)) +// CHECK-TLS-NEXT: [[DOTZ__VOID_ADDR:%.*]] = call ptr @__kmpc_aligned_alloc(i32 [[TMP0]], i64 8, i64 4, ptr inttoptr (i64 1 to ptr)) +// CHECK-TLS-NEXT: store ptr [[DOTZ__VOID_ADDR]], ptr [[TMP]], align 8 +// CHECK-TLS-NEXT: [[TMP1:%.*]] = load ptr, ptr [[TMP]], align 8 +// CHECK-TLS-NEXT: [[TMP2:%.*]] = load float, ptr [[TMP1]], align 4 +// CHECK-TLS-NEXT: [[ADD:%.*]] = fadd float 8.000000e+00, [[TMP2]] +// CHECK-TLS-NEXT: [[TMP3:%.*]] = load i32, ptr [[DOTA__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP3]] to float +// CHECK-TLS-NEXT: [[ADD1:%.*]] = fadd float [[CONV]], [[ADD]] +// CHECK-TLS-NEXT: [[CONV2:%.*]] = fptosi float [[ADD1]] to i32 +// CHECK-TLS-NEXT: store i32 [[CONV2]], ptr [[DOTA__VOID_ADDR]], align 4 +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTZ__VOID_ADDR]], ptr inttoptr (i64 1 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_free(i32 [[TMP0]], ptr [[DOTA__VOID_ADDR]], ptr inttoptr (i64 1 to ptr)) +// CHECK-TLS-NEXT: call void @__kmpc_barrier(ptr @[[GLOB2]], i32 [[TMP0]]) +// CHECK-TLS-NEXT: ret void +// +// +// SIMD-ONLY0-LABEL: define dso_local noundef i32 @main( +// SIMD-ONLY0-SAME: ) #[[ATTR0:[0-9]+]] { +// SIMD-ONLY0-NEXT: [[ENTRY:.*:]] +// SIMD-ONLY0-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[A:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[A1:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V2:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V4:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V6:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V8:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V10:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V12:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[B:%.*]] = alloca double, align 8 +// SIMD-ONLY0-NEXT: [[TEMP:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// SIMD-ONLY0-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4 +// SIMD-ONLY0-NEXT: [[INC:%.*]] = add nsw i32 [[TMP0]], 1 +// SIMD-ONLY0-NEXT: store i32 [[INC]], ptr [[A]], align 4 +// SIMD-ONLY0-NEXT: store i32 2, ptr [[A1]], align 4 +// SIMD-ONLY0-NEXT: [[TMP1:%.*]] = load i32, ptr [[V2]], align 4 +// SIMD-ONLY0-NEXT: [[INC3:%.*]] = add nsw i32 [[TMP1]], 1 +// SIMD-ONLY0-NEXT: store i32 [[INC3]], ptr [[V2]], align 4 +// SIMD-ONLY0-NEXT: [[TMP2:%.*]] = load i32, ptr [[V4]], align 4 +// SIMD-ONLY0-NEXT: [[INC5:%.*]] = add nsw i32 [[TMP2]], 1 +// SIMD-ONLY0-NEXT: store i32 [[INC5]], ptr [[V4]], align 4 +// SIMD-ONLY0-NEXT: [[TMP3:%.*]] = load i32, ptr [[V6]], align 4 +// SIMD-ONLY0-NEXT: [[INC7:%.*]] = add nsw i32 [[TMP3]], 1 +// SIMD-ONLY0-NEXT: store i32 [[INC7]], ptr [[V6]], align 4 +// SIMD-ONLY0-NEXT: [[TMP4:%.*]] = load i32, ptr [[V8]], align 4 +// SIMD-ONLY0-NEXT: [[INC9:%.*]] = add nsw i32 [[TMP4]], 1 +// SIMD-ONLY0-NEXT: store i32 [[INC9]], ptr [[V8]], align 4 +// SIMD-ONLY0-NEXT: [[TMP5:%.*]] = load i32, ptr [[V10]], align 4 +// SIMD-ONLY0-NEXT: [[INC11:%.*]] = add nsw i32 [[TMP5]], 1 +// SIMD-ONLY0-NEXT: store i32 [[INC11]], ptr [[V10]], align 4 +// SIMD-ONLY0-NEXT: [[TMP6:%.*]] = load i32, ptr [[V12]], align 4 +// SIMD-ONLY0-NEXT: [[INC13:%.*]] = add nsw i32 [[TMP6]], 1 +// SIMD-ONLY0-NEXT: store i32 [[INC13]], ptr [[V12]], align 4 +// SIMD-ONLY0-NEXT: store double 3.000000e+00, ptr [[B]], align 8 +// SIMD-ONLY0-NEXT: [[CALL:%.*]] = call noundef i32 @_Z3fooIiL22omp_allocator_handle_t6ELj8EET_v() +// SIMD-ONLY0-NEXT: [[TMP7:%.*]] = load i32, ptr [[TEMP]], align 4 +// SIMD-ONLY0-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP7]], [[CALL]] +// SIMD-ONLY0-NEXT: store i32 [[ADD]], ptr [[TEMP]], align 4 +// SIMD-ONLY0-NEXT: [[TMP8:%.*]] = load i32, ptr @_ZZ4mainE4temp, align 4 +// SIMD-ONLY0-NEXT: [[TMP9:%.*]] = load i32, ptr @_ZN2ns1aE, align 4 +// SIMD-ONLY0-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP8]], [[TMP9]] +// SIMD-ONLY0-NEXT: ret i32 [[ADD14]] +// +// +// SIMD-ONLY0-LABEL: define linkonce_odr noundef i32 @_Z3fooIiL22omp_allocator_handle_t6ELj8EET_v( +// SIMD-ONLY0-SAME: ) #[[ATTR1:[0-9]+]] comdat { +// SIMD-ONLY0-NEXT: [[ENTRY:.*:]] +// SIMD-ONLY0-NEXT: [[V:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V1:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[V2:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[TMP0:%.*]] = load i32, ptr @_ZN2STIiE1mE, align 4 +// SIMD-ONLY0-NEXT: store i32 [[TMP0]], ptr [[V1]], align 4 +// SIMD-ONLY0-NEXT: [[TMP1:%.*]] = load i32, ptr [[V2]], align 4 +// SIMD-ONLY0-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 +// SIMD-ONLY0-NEXT: store i32 [[INC]], ptr [[V2]], align 4 +// SIMD-ONLY0-NEXT: [[TMP2:%.*]] = load i32, ptr [[V]], align 4 +// SIMD-ONLY0-NEXT: ret i32 [[TMP2]] +// +// +// SIMD-ONLY0-LABEL: define dso_local void @_Z3bariRf( +// SIMD-ONLY0-SAME: i32 noundef [[A:%.*]], ptr noundef nonnull align 4 dereferenceable(4) [[Z:%.*]]) #[[ATTR1]] { +// SIMD-ONLY0-NEXT: [[ENTRY:.*:]] +// SIMD-ONLY0-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[Z_ADDR:%.*]] = alloca ptr, align 8 +// SIMD-ONLY0-NEXT: [[A1:%.*]] = alloca i32, align 4 +// SIMD-ONLY0-NEXT: [[Z2:%.*]] = alloca float, align 4 +// SIMD-ONLY0-NEXT: [[TMP:%.*]] = alloca ptr, align 8 +// SIMD-ONLY0-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 +// SIMD-ONLY0-NEXT: store ptr [[Z]], ptr [[Z_ADDR]], align 8 +// SIMD-ONLY0-NEXT: store ptr [[Z2]], ptr [[TMP]], align 8 +// SIMD-ONLY0-NEXT: [[TMP0:%.*]] = load ptr, ptr [[TMP]], align 8 +// SIMD-ONLY0-NEXT: [[TMP1:%.*]] = load float, ptr [[TMP0]], align 4 +// SIMD-ONLY0-NEXT: [[ADD:%.*]] = fadd float 8.000000e+00, [[TMP1]] +// SIMD-ONLY0-NEXT: [[TMP2:%.*]] = load i32, ptr [[A1]], align 4 +// SIMD-ONLY0-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP2]] to float +// SIMD-ONLY0-NEXT: [[ADD3:%.*]] = fadd float [[CONV]], [[ADD]] +// SIMD-ONLY0-NEXT: [[CONV4:%.*]] = fptosi float [[ADD3]] to i32 +// SIMD-ONLY0-NEXT: store i32 [[CONV4]], ptr [[A1]], align 4 +// SIMD-ONLY0-NEXT: ret void +// diff --git a/clang/test/OpenMP/allocate_modifiers_messages.cpp b/clang/test/OpenMP/allocate_modifiers_messages.cpp new file mode 100644 index 0000000000000..6867e78a89ee9 --- /dev/null +++ b/clang/test/OpenMP/allocate_modifiers_messages.cpp @@ -0,0 +1,159 @@ +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 %s + +typedef enum omp_allocator_handle_t { + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, +} omp_allocator_handle_t; + +int myAlloc() { + return 100; +} + +int main() { + int a, b, c; + // expected-error@+4 {{expected '('}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(c) allocate(allocator + // expected-error@+6 {{expected expression}} + // expected-error@+5 {{expected ')'}} + // expected-note@+4 {{to match this '('}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(c) allocate(allocator( + // expected-error@+4 {{expected expression}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(c) allocate(allocator() + // expected-error@+2 {{expected expression}} + // expected-error@+1 {{expected expression}} + #pragma omp scope private(c) allocate(allocator()) + // expected-error@+6 {{expected ')'}} + // expected-note@+5 {{to match this '('}} + // expected-error@+4 {{missing ':' after allocate clause modifier}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(c) allocate(allocator(omp_default_mem_alloc + // expected-error@+6 {{missing ':' after allocate clause modifier}} + // expected-error@+5 {{expected expression}} + // expected-error@+4 {{expected ')'}} + // expected-note@+3 {{to match this '('}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(c) allocate(allocator(omp_large_cap_mem_alloc: + // expected-error@+4 {{missing ':' after allocate clause modifier}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc) + // expected-error@+2 {{missing ':' after allocate clause modifier}} + // expected-error@+1 {{expected expression}} + #pragma omp scope private(c) allocate(allocator(omp_high_bw_mem_alloc)) + // expected-error@+1 {{expected expression}} + #pragma omp scope private(c) allocate(allocator(omp_low_lat_mem_alloc):) + // expected-error@+6 {{expected ')'}} + // expected-note@+5 {{to match this '('}} + // expected-error@+4 {{missing ':' after allocate clause modifier}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(c) allocate(allocator(omp_cgroup_mem_alloc:) + // expected-error@+4 {{expected ')'}} + // expected-note@+3 {{to match this '('}} + // expected-error@+2 {{missing ':' after allocate clause modifier}} + // expected-error@+1 {{expected expression}} + #pragma omp scope private(c) allocate(allocator(omp_pteam_mem_alloc:)) + // expected-error@+4 {{expected ')'}} + // expected-note@+3 {{to match this '('}} + // expected-error@+2 {{missing ':' after allocate clause modifier}} + // expected-error@+1 {{expected expression}} + #pragma omp scope private(c) allocate(allocator(omp_thread_mem_alloc:c)) + // expected-error@+1 {{expected variable name}} + #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc):1) + // expected-error@+1 {{expected variable name}} + #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc):-10) + // expected-error@+4 {{expected ',' or ')' in 'allocate' clause}} + // expected-error@+3 {{expected ')'}} + // expected-warning@+2 {{extra tokens at the end of '#pragma omp scope' are ignored}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(a,b,c) allocate(allocator(omp_const_mem_alloc):c:b;a) + // expected-error@+1 {{initializing 'const omp_allocator_handle_t' with an expression of incompatible type 'int'}} + #pragma omp scope private(c,a,b) allocate(allocator(myAlloc()):a,b,c) + // expected-error@+2 {{missing ':' after allocate clause modifier}} + // expected-error@+1 {{expected expression}} + #pragma omp scope private(c) allocate(allocator(omp_default_mem_alloc);c) + // expected-error@+2 {{duplicate modifier 'allocator' in 'allocate' clause}} + // expected-warning@+1 {{aligned clause will be ignored because the requested alignment is not a power of 2}} + #pragma omp scope private(a) allocate(allocator(omp_default_mem_alloc), allocator(omp_default_mem_alloc), align(3) : a) + // expected-error@+4 {{expected '('}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(a) allocate(allocator + // expected-error@+4 {{expected '('}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(b) allocate(align + // expected-error@+1 {{duplicate modifier 'align' in 'allocate' clause}} + #pragma omp scope private(a) allocate(align(8), align(4) : a) + // expected-error@+5 {{use of undeclared identifier 'align'}} + // expected-error@+4 {{expected ',' or ')' in 'allocate' clause}} + // expected-error@+3 {{expected ')'}} + // expected-note@+2 {{to match this '('}} + // expected-error@+1 {{expected variable name}} + #pragma omp scope private(a) allocate(omp_default_mem_alloc, align(8) : a) + // expected-error@+3 {{expected modifier in 'allocate' clause}} + // expected-error@+2 {{missing ':' after allocate clause modifier}} + // expected-error@+1 {{expected expression}} + #pragma omp scope private(a) allocate(align(8), omp_default_mem_alloc : a) + // expected-error@+5 {{expected ',' or ')' in 'allocate' clause}} + // expected-error@+4 {{expected ')'}} + // expected-note@+3 {{to match this '('}} + // expected-error@+2 {{expected variable name}} + // expected-error@+1 {{expected variable name}} + #pragma omp scope private(a) allocate(omp_default_mem_alloc, omp_default_mem_alloc : a) + // expected-error@+2 {{use of undeclared identifier 'undefinedVar'}} + // expected-error@+1 {{expected expression}} + #pragma omp scope private(a) allocate(undefinedVar : a) + // expected-error@+1 {{expected expression}} + #pragma omp scope private(a) allocate(align(8), allocator(omp_default_mem_alloc) : ) + // expected-error@+2 {{missing ':' after allocate clause modifier}} + // expected-error@+1 {{expected expression}} + #pragma omp scope private(a) allocate(align(8), allocator(omp_default_mem_alloc) ) + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(a) allocate(align(8), allocator(omp_default_mem_alloc) : + + // expected-error@+4 {{missing ':' after allocate clause modifier}} + // expected-error@+3 {{expected expression}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(a) allocate(align(8), allocator(omp_default_mem_alloc) + // expected-error@+4 {{expected '('}} + // expected-error@+3 {{expected '('}} + // expected-error@+2 {{expected expression}} + // expected-error@+1 {{use of undeclared identifier 'allocator'}} + #pragma omp scope private(a) allocate(align, allocator : ) + // expected-error@+7 {{expected expression}} + // expected-error@+6 {{expected expression}} + // expected-error@+5 {{expected expression}} + // expected-error@+4 {{use of undeclared identifier 'allocator'}} + // expected-error@+3 {{expected ',' or ')' in 'allocate' clause}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp scope private(a) allocate(align(), allocator() : ) + ++a; +}</int,></omp_allocator_handle_t,></int,></sourcelocation,></openmpallocateclausemodifier,>