[clang] [clang][OpenMP] Add 'align' modifier for 'allocate' clause (PR #121814)
David Pagan via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 6 10:41:11 PST 2025
https://github.com/ddpagan created https://github.com/llvm/llvm-project/pull/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
>From c2c2c4c46c3ea615e86484b9f9a14a74fab21295 Mon Sep 17 00:00:00 2001
From: Dave Pagan <dave.pagan at amd.com>
Date: Fri, 22 Nov 2024 10:35:40 -0600
Subject: [PATCH] [clang][OpenMP] Add 'align' modifier for 'allocate' clause
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
---
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/AST/OpenMPClause.h | 92 +++-
.../clang/Basic/DiagnosticParseKinds.td | 2 +
clang/include/clang/Basic/OpenMPKinds.def | 1 +
clang/include/clang/Basic/OpenMPKinds.h | 4 +
clang/include/clang/Sema/SemaOpenMP.h | 20 +-
clang/lib/AST/OpenMPClause.cpp | 58 ++-
clang/lib/Parse/ParseOpenMP.cpp | 95 +++-
clang/lib/Sema/SemaOpenMP.cpp | 102 +++--
clang/lib/Sema/TreeTransform.h | 30 +-
clang/lib/Serialization/ASTReader.cpp | 6 +-
clang/lib/Serialization/ASTWriter.cpp | 4 +-
.../allocate_allocator_modifier_codegen.cpp | 255 -----------
.../allocate_allocator_modifier_messages.cpp | 97 -----
...t.cpp => allocate_modifiers_ast_print.cpp} | 77 +++-
.../OpenMP/allocate_modifiers_codegen.cpp | 409 ++++++++++++++++++
.../OpenMP/allocate_modifiers_messages.cpp | 159 +++++++
17 files changed, 961 insertions(+), 451 deletions(-)
delete mode 100644 clang/test/OpenMP/allocate_allocator_modifier_codegen.cpp
delete mode 100644 clang/test/OpenMP/allocate_allocator_modifier_messages.cpp
rename clang/test/OpenMP/{allocate_allocator_modifier_ast_print.cpp => allocate_modifiers_ast_print.cpp} (51%)
create mode 100644 clang/test/OpenMP/allocate_modifiers_codegen.cpp
create mode 100644 clang/test/OpenMP/allocate_modifiers_messages.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index acd9dd9298ce1e..25d390f69bcea3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1284,6 +1284,7 @@ OpenMP Support
- Changed the OpenMP DeviceRTL to use 'generic' IR. The
``LIBOMPTARGET_DEVICE_ARCHITECTURES`` CMake argument is now unused and will
always build support for AMDGPU and NVPTX targets.
+- 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..4032cbcb614e73 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -4530,32 +4530,87 @@ 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:
+ assert(false && "Unexpected allocate modifier");
+ break;
+ }
} 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 +4887,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 +4905,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..9b77031ca16670 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5285,6 +5285,7 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
}
for (OMPClause *C : AllocateRange) {
auto *AC = cast<OMPAllocateClause>(C);
+ // TODO: Check alignment?
if (S.getLangOpts().OpenMP >= 50 &&
!Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
@@ -5320,6 +5321,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 +5333,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 +15618,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 +17156,25 @@ 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 (auto NumModifiers = Data.AllocClauseModifiers.size()) {
+ Modifier1 = Data.AllocClauseModifiers[0];
+ Modifier1Loc = Data.AllocClauseModifiersLoc[0];
+ assert(NumModifiers <= 2 && "More allocate modifiers than expected");
+ if (NumModifiers == 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 0121be81bc6acd..f0958168d0c511 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<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.
@@ -11206,6 +11209,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()) {
@@ -11215,7 +11225,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 fccd79bf745203..8f105102563a22 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -11824,10 +11824,14 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
}
void OMPClauseReader::VisitOMPAllocateClause(OMPAllocateClause *C) {
- C->setAllocatorModifier(Record.readEnum<OpenMPAllocateClauseModifier>());
+ C->setFirstAllocateModifier(
+ static_cast<OpenMPAllocateClauseModifier>(Record.readInt()));
+ C->setSecondAllocateModifier(
+ static_cast<OpenMPAllocateClauseModifier>(Record.readInt()));
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 7fa9322e7551f7..3485052bbc4fdc 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.push_back(C->getFirstAllocateModifier());
+ Record.push_back(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