[clang] ad38e24 - [clang][OpenMP] Add 'align' modifier for 'allocate' clause (#121814)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 13 05:44:52 PST 2025
Author: David Pagan
Date: 2025-01-13T05:44:48-08:00
New Revision: ad38e24eb74e97148faec97c4f843b87768b6e9b
URL: https://github.com/llvm/llvm-project/commit/ad38e24eb74e97148faec97c4f843b87768b6e9b
DIFF: https://github.com/llvm/llvm-project/commit/ad38e24eb74e97148faec97c4f843b87768b6e9b.diff
LOG: [clang][OpenMP] Add 'align' modifier for 'allocate' clause (#121814)
The 'align' modifier is now accepted in the 'allocate' clause. Added LIT
tests covering codegen, PCH, template handling, and serialization for
'align' modifier.
Added support for align-modifier to release notes.
Testing
- New allocate modifier LIT tests.
- OpenMP LIT tests.
- check-all
Added:
clang/test/OpenMP/allocate_modifiers_ast_print.cpp
clang/test/OpenMP/allocate_modifiers_codegen.cpp
clang/test/OpenMP/allocate_modifiers_messages.cpp
Modified:
clang/docs/OpenMPSupport.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/OpenMPClause.h
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/OpenMPKinds.def
clang/include/clang/Basic/OpenMPKinds.h
clang/include/clang/Sema/SemaOpenMP.h
clang/lib/AST/OpenMPClause.cpp
clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
Removed:
clang/test/OpenMP/allocate_allocator_modifier_ast_print.cpp
clang/test/OpenMP/allocate_allocator_modifier_codegen.cpp
clang/test/OpenMP/allocate_allocator_modifier_messages.cpp
################################################################################
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index a1cb7fe359ebf8..673c34bf08a4a4 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 8f4adbcd705181..9eeb872aa57d79 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1370,6 +1370,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 d2f5267e4da5ea..b9088eff3bb52e 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<OMPAllocateClause>(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<OMPAllocateClause>(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<Expr *> VL);
+ Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc,
+ OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc,
+ OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc,
+ SourceLocation EndLoc, ArrayRef<Expr *> 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 86fcae209c40db..3309f59a981fc1 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<OpenMPExtensions>;
+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 3f25e7aafe23b6..76a861f416fd57 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 900ad6ca6d66f6..3e5da2a6abc017 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 3d1cc4fab1c10f..a056a96f502333 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<Expr *> VarList, SourceLocation StartLoc,
- SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+ OMPClause *
+ ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment,
+ OpenMPAllocateClauseModifier FirstModifier,
+ SourceLocation FirstModifierLoc,
+ OpenMPAllocateClauseModifier SecondModifier,
+ SourceLocation SecondModifierLoc,
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation ColonLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// Called on well-formed 'private' clause.
OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 4246ba95d827f1..532933d6183ce7 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<Expr *> 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<Expr *> VL) {
// Allocate space for private variables and initializer expressions.
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(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 b4e973bc84a7b0..89b83938f352df 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<OpenMPAllocateClauseModifier>(
+ ExprResult Val;
+ SourceLocation RLoc;
+ bool AllocatorSeen = false;
+ bool AlignSeen = false;
+ SourceLocation CurrentModifierLoc = Tok.getLocation();
+ auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
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<OpenMPAllocateClauseModifier>(
+ 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 66ff92f554fc42..b83b2b12f4a230 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<Expr *> VarList,
}
OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
- Expr *Allocator, OpenMPAllocateClauseModifier AllocClauseModifier,
- ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation ColonLoc, SourceLocation EndLoc) {
-
+ Expr *Allocator, Expr *Alignment,
+ OpenMPAllocateClauseModifier FirstAllocateModifier,
+ SourceLocation FirstAllocateModifierLoc,
+ OpenMPAllocateClauseModifier SecondAllocateModifier,
+ SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> 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<OMPDynamicAllocatorsClause>())
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<Expr *, 8> 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<Expr *> VarList,
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 4a3c739ecbeab8..4fae2ccb5f6d0a 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
diff erent behavior.
- OMPClause *RebuildOMPAllocateClause(Expr *Allocate,
- OpenMPAllocateClauseModifier ACModifier,
- ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc) {
+ OMPClause *
+ RebuildOMPAllocateClause(Expr *Allocate, Expr *Alignment,
+ OpenMPAllocateClauseModifier FirstModifier,
+ SourceLocation FirstModifierLoc,
+ OpenMPAllocateClauseModifier SecondModifier,
+ SourceLocation SecondModifierLoc,
+ ArrayRef<Expr *> 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<Derived>::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<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
for (auto *VE : C->varlist()) {
@@ -11233,7 +11243,9 @@ TreeTransform<Derived>::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 b53f99732cacce..7361cace49dd7b 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<OpenMPAllocateClauseModifier>());
+ C->setFirstAllocateModifier(Record.readEnum<OpenMPAllocateClauseModifier>());
+ C->setSecondAllocateModifier(Record.readEnum<OpenMPAllocateClauseModifier>());
C->setLParenLoc(Record.readSourceLocation());
C->setColonLoc(Record.readSourceLocation());
C->setAllocator(Record.readSubExpr());
+ C->setAlignment(Record.readSubExpr());
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 39004fd4d4c376..345d496a933123 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 1bf927ebb2eb7c..00000000000000
--- 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 <class T>
-struct ST {
- static T m;
-};
-
-template <class T, omp_allocator_handle_t TY> T foo() {
- T v;
- #pragma omp scope private(v) allocate(allocator(TY):v)
- v = ST<T>::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<int>::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 160c4996c12195..00000000000000
--- 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 at +4 {{expected '('}}
- // expected-error at +3 {{expected expression}}
- // expected-error at +2 {{expected ')'}}
- // expected-note at +1 {{to match this '('}}
- #pragma omp scope private(c) allocate(allocator
- // expected-error at +6 {{expected expression}}
- // expected-error at +5 {{expected ')'}}
- // expected-note at +4 {{to match this '('}}
- // expected-error at +3 {{expected expression}}
- // expected-error at +2 {{expected ')'}}
- // expected-note at +1 {{to match this '('}}
- #pragma omp scope private(c) allocate(allocator(
- // expected-error at +4 {{expected expression}}
- // expected-error at +3 {{expected expression}}
- // expected-error at +2 {{expected ')'}}
- // expected-note at +1 {{to match this '('}}
- #pragma omp scope private(c) allocate(allocator()
- // expected-error at +2 {{expected expression}}
- // expected-error at +1 {{expected expression}}
- #pragma omp scope private(c) allocate(allocator())
- // expected-error at +6 {{expected ')'}}
- // expected-note at +5 {{to match this '('}}
- // expected-error at +4 {{missing ':' after allocator modifier}}
- // expected-error at +3 {{expected expression}}
- // expected-error at +2 {{expected ')'}}
- // expected-note at +1 {{to match this '('}}
- #pragma omp scope private(c) allocate(allocator(omp_default_mem_alloc
- // expected-error at +6 {{missing ':' after allocator modifier}}
- // expected-error at +5 {{expected expression}}
- // expected-error at +4 {{expected ')'}}
- // expected-note at +3 {{to match this '('}}
- // expected-error at +2 {{expected ')'}}
- // expected-note at +1 {{to match this '('}}
- #pragma omp scope private(c) allocate(allocator(omp_large_cap_mem_alloc:
- // expected-error at +4 {{missing ':' after allocator modifier}}
- // expected-error at +3 {{expected expression}}
- // expected-error at +2 {{expected ')'}}
- // expected-note at +1 {{to match this '('}}
- #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc)
- // expected-error at +2 {{missing ':' after allocator modifier}}
- // expected-error at +1 {{expected expression}}
- #pragma omp scope private(c) allocate(allocator(omp_high_bw_mem_alloc))
- // expected-error at +1 {{expected expression}}
- #pragma omp scope private(c) allocate(allocator(omp_low_lat_mem_alloc):)
- // expected-error at +6 {{expected ')'}}
- // expected-note at +5 {{to match this '('}}
- // expected-error at +4 {{missing ':' after allocator modifier}}
- // expected-error at +3 {{expected expression}}
- // expected-error at +2 {{expected ')'}}
- // expected-note at +1 {{to match this '('}}
- #pragma omp scope private(c) allocate(allocator(omp_cgroup_mem_alloc:)
- // expected-error at +4 {{expected ')'}}
- // expected-note at +3 {{to match this '('}}
- // expected-error at +2 {{missing ':' after allocator modifier}}
- // expected-error at +1 {{expected expression}}
- #pragma omp scope private(c) allocate(allocator(omp_pteam_mem_alloc:))
- // expected-error at +4 {{expected ')'}}
- // expected-note at +3 {{to match this '('}}
- // expected-error at +2 {{missing ':' after allocator modifier}}
- // expected-error at +1 {{expected expression}}
- #pragma omp scope private(c) allocate(allocator(omp_thread_mem_alloc:c))
- // expected-error at +1 {{expected variable name}}
- #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc):1)
- // expected-error at +1 {{expected variable name}}
- #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc):-10)
- // expected-error at +4 {{expected ',' or ')' in 'allocate' clause}}
- // expected-error at +3 {{expected ')'}}
- // expected-warning at +2 {{extra tokens at the end of '#pragma omp scope' are ignored}}
- // expected-note at +1 {{to match this '('}}
- #pragma omp scope private(a,b,c) allocate(allocator(omp_const_mem_alloc):c:b;a)
- // expected-error at +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 at +2 {{missing ':' after allocator modifier}}
- // expected-error at +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 15f3f1dd9bbb92..436647be75da3f 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<typename T, unsigned al>
+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 00000000000000..d798e9b3435f0e
--- /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 <class T>
+struct ST {
+ static T m;
+};
+
+template <class T, omp_allocator_handle_t TY, unsigned al> T foo() {
+ T v;
+ #pragma omp scope private(v) allocate(allocator(TY):v)
+ v = ST<T>::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, omp_cgroup_mem_alloc, 8>();
+ return temp+ns::a;
+}
+
+extern template int ST<int>::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 00000000000000..6867e78a89ee90
--- /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 at +4 {{expected '('}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(c) allocate(allocator
+ // expected-error at +6 {{expected expression}}
+ // expected-error at +5 {{expected ')'}}
+ // expected-note at +4 {{to match this '('}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(c) allocate(allocator(
+ // expected-error at +4 {{expected expression}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(c) allocate(allocator()
+ // expected-error at +2 {{expected expression}}
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(c) allocate(allocator())
+ // expected-error at +6 {{expected ')'}}
+ // expected-note at +5 {{to match this '('}}
+ // expected-error at +4 {{missing ':' after allocate clause modifier}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(c) allocate(allocator(omp_default_mem_alloc
+ // expected-error at +6 {{missing ':' after allocate clause modifier}}
+ // expected-error at +5 {{expected expression}}
+ // expected-error at +4 {{expected ')'}}
+ // expected-note at +3 {{to match this '('}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(c) allocate(allocator(omp_large_cap_mem_alloc:
+ // expected-error at +4 {{missing ':' after allocate clause modifier}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc)
+ // expected-error at +2 {{missing ':' after allocate clause modifier}}
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(c) allocate(allocator(omp_high_bw_mem_alloc))
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(c) allocate(allocator(omp_low_lat_mem_alloc):)
+ // expected-error at +6 {{expected ')'}}
+ // expected-note at +5 {{to match this '('}}
+ // expected-error at +4 {{missing ':' after allocate clause modifier}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(c) allocate(allocator(omp_cgroup_mem_alloc:)
+ // expected-error at +4 {{expected ')'}}
+ // expected-note at +3 {{to match this '('}}
+ // expected-error at +2 {{missing ':' after allocate clause modifier}}
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(c) allocate(allocator(omp_pteam_mem_alloc:))
+ // expected-error at +4 {{expected ')'}}
+ // expected-note at +3 {{to match this '('}}
+ // expected-error at +2 {{missing ':' after allocate clause modifier}}
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(c) allocate(allocator(omp_thread_mem_alloc:c))
+ // expected-error at +1 {{expected variable name}}
+ #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc):1)
+ // expected-error at +1 {{expected variable name}}
+ #pragma omp scope private(c) allocate(allocator(omp_const_mem_alloc):-10)
+ // expected-error at +4 {{expected ',' or ')' in 'allocate' clause}}
+ // expected-error at +3 {{expected ')'}}
+ // expected-warning at +2 {{extra tokens at the end of '#pragma omp scope' are ignored}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(a,b,c) allocate(allocator(omp_const_mem_alloc):c:b;a)
+ // expected-error at +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 at +2 {{missing ':' after allocate clause modifier}}
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(c) allocate(allocator(omp_default_mem_alloc);c)
+ // expected-error at +2 {{duplicate modifier 'allocator' in 'allocate' clause}}
+ // expected-warning at +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 at +4 {{expected '('}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(a) allocate(allocator
+ // expected-error at +4 {{expected '('}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(b) allocate(align
+ // expected-error at +1 {{duplicate modifier 'align' in 'allocate' clause}}
+ #pragma omp scope private(a) allocate(align(8), align(4) : a)
+ // expected-error at +5 {{use of undeclared identifier 'align'}}
+ // expected-error at +4 {{expected ',' or ')' in 'allocate' clause}}
+ // expected-error at +3 {{expected ')'}}
+ // expected-note at +2 {{to match this '('}}
+ // expected-error at +1 {{expected variable name}}
+ #pragma omp scope private(a) allocate(omp_default_mem_alloc, align(8) : a)
+ // expected-error at +3 {{expected modifier in 'allocate' clause}}
+ // expected-error at +2 {{missing ':' after allocate clause modifier}}
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(a) allocate(align(8), omp_default_mem_alloc : a)
+ // expected-error at +5 {{expected ',' or ')' in 'allocate' clause}}
+ // expected-error at +4 {{expected ')'}}
+ // expected-note at +3 {{to match this '('}}
+ // expected-error at +2 {{expected variable name}}
+ // expected-error at +1 {{expected variable name}}
+ #pragma omp scope private(a) allocate(omp_default_mem_alloc, omp_default_mem_alloc : a)
+ // expected-error at +2 {{use of undeclared identifier 'undefinedVar'}}
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(a) allocate(undefinedVar : a)
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(a) allocate(align(8), allocator(omp_default_mem_alloc) : )
+ // expected-error at +2 {{missing ':' after allocate clause modifier}}
+ // expected-error at +1 {{expected expression}}
+ #pragma omp scope private(a) allocate(align(8), allocator(omp_default_mem_alloc) )
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(a) allocate(align(8), allocator(omp_default_mem_alloc) :
+
+ // expected-error at +4 {{missing ':' after allocate clause modifier}}
+ // expected-error at +3 {{expected expression}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(a) allocate(align(8), allocator(omp_default_mem_alloc)
+ // expected-error at +4 {{expected '('}}
+ // expected-error at +3 {{expected '('}}
+ // expected-error at +2 {{expected expression}}
+ // expected-error at +1 {{use of undeclared identifier 'allocator'}}
+ #pragma omp scope private(a) allocate(align, allocator : )
+ // expected-error at +7 {{expected expression}}
+ // expected-error at +6 {{expected expression}}
+ // expected-error at +5 {{expected expression}}
+ // expected-error at +4 {{use of undeclared identifier 'allocator'}}
+ // expected-error at +3 {{expected ',' or ')' in 'allocate' clause}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp scope private(a) allocate(align(), allocator() : )
+ ++a;
+}
More information about the cfe-commits
mailing list