[OpenMP][Clang] Add parser/semantic support for dyn_groupprivate clause (#152651)
This PR adds support for the `dyn_groupprivate` clause, which will be part of OpenMP 6.1. This feature allows users to request dynamic shared memory on target regions. --------- Co-authored-by: Krzysztof Parzyszek <Krzysztof.Parzyszek@amd.com>
This commit is contained in:
parent
3511388013
commit
64ff52a5e9
@ -10068,6 +10068,152 @@ public:
|
||||
Expr *getSize() const { return getStmtAs<Expr>(); }
|
||||
};
|
||||
|
||||
/// This represents 'dyn_groupprivate' clause in '#pragma omp target ...'
|
||||
/// and '#pragma omp teams ...' directives.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp target [...] dyn_groupprivate(a,b: N)
|
||||
/// \endcode
|
||||
class OMPDynGroupprivateClause : public OMPClause, public OMPClauseWithPreInit {
|
||||
friend class OMPClauseReader;
|
||||
|
||||
/// Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
|
||||
/// Modifiers for 'dyn_groupprivate' clause.
|
||||
enum { SIMPLE, FALLBACK, NUM_MODIFIERS };
|
||||
unsigned Modifiers[NUM_MODIFIERS];
|
||||
|
||||
/// Locations of modifiers.
|
||||
SourceLocation ModifiersLoc[NUM_MODIFIERS];
|
||||
|
||||
/// The size of the dyn_groupprivate.
|
||||
Expr *Size = nullptr;
|
||||
|
||||
/// Set the first dyn_groupprivate modifier.
|
||||
///
|
||||
/// \param M The modifier.
|
||||
void setDynGroupprivateModifier(OpenMPDynGroupprivateClauseModifier M) {
|
||||
Modifiers[SIMPLE] = M;
|
||||
}
|
||||
|
||||
/// Set the second dyn_groupprivate modifier.
|
||||
///
|
||||
/// \param M The modifier.
|
||||
void setDynGroupprivateFallbackModifier(
|
||||
OpenMPDynGroupprivateClauseFallbackModifier M) {
|
||||
Modifiers[FALLBACK] = M;
|
||||
}
|
||||
|
||||
/// Set location of the first dyn_groupprivate modifier.
|
||||
void setDynGroupprivateModifierLoc(SourceLocation Loc) {
|
||||
ModifiersLoc[SIMPLE] = Loc;
|
||||
}
|
||||
|
||||
/// Set location of the second dyn_groupprivate modifier.
|
||||
void setDynGroupprivateFallbackModifierLoc(SourceLocation Loc) {
|
||||
ModifiersLoc[FALLBACK] = Loc;
|
||||
}
|
||||
|
||||
/// Sets the location of '('.
|
||||
///
|
||||
/// \param Loc Location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
|
||||
/// Set size.
|
||||
///
|
||||
/// \param E Size.
|
||||
void setSize(Expr *E) { Size = E; }
|
||||
|
||||
public:
|
||||
/// Build 'dyn_groupprivate' clause with a size expression \a Size.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param Size Size.
|
||||
/// \param M1 The first modifier applied to 'dyn_groupprivate' clause.
|
||||
/// \param M1Loc Location of the first modifier.
|
||||
/// \param M2 The second modifier applied to 'dyn_groupprivate' clause.
|
||||
/// \param M2Loc Location of the second modifier.
|
||||
OMPDynGroupprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, Expr *Size, Stmt *HelperSize,
|
||||
OpenMPDirectiveKind CaptureRegion,
|
||||
OpenMPDynGroupprivateClauseModifier M1,
|
||||
SourceLocation M1Loc,
|
||||
OpenMPDynGroupprivateClauseFallbackModifier M2,
|
||||
SourceLocation M2Loc)
|
||||
: OMPClause(llvm::omp::OMPC_dyn_groupprivate, StartLoc, EndLoc),
|
||||
OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Size(Size) {
|
||||
setPreInitStmt(HelperSize, CaptureRegion);
|
||||
Modifiers[SIMPLE] = M1;
|
||||
Modifiers[FALLBACK] = M2;
|
||||
ModifiersLoc[SIMPLE] = M1Loc;
|
||||
ModifiersLoc[FALLBACK] = M2Loc;
|
||||
}
|
||||
|
||||
/// Build an empty clause.
|
||||
explicit OMPDynGroupprivateClause()
|
||||
: OMPClause(llvm::omp::OMPC_dyn_groupprivate, SourceLocation(),
|
||||
SourceLocation()),
|
||||
OMPClauseWithPreInit(this) {
|
||||
Modifiers[SIMPLE] = OMPC_DYN_GROUPPRIVATE_unknown;
|
||||
Modifiers[FALLBACK] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
|
||||
}
|
||||
|
||||
/// Get the first modifier of the clause.
|
||||
OpenMPDynGroupprivateClauseModifier getDynGroupprivateModifier() const {
|
||||
return static_cast<OpenMPDynGroupprivateClauseModifier>(Modifiers[SIMPLE]);
|
||||
}
|
||||
|
||||
/// Get the second modifier of the clause.
|
||||
OpenMPDynGroupprivateClauseFallbackModifier
|
||||
getDynGroupprivateFallbackModifier() const {
|
||||
return static_cast<OpenMPDynGroupprivateClauseFallbackModifier>(
|
||||
Modifiers[FALLBACK]);
|
||||
}
|
||||
|
||||
/// Get location of '('.
|
||||
SourceLocation getLParenLoc() { return LParenLoc; }
|
||||
|
||||
/// Get the first modifier location.
|
||||
SourceLocation getDynGroupprivateModifierLoc() const {
|
||||
return ModifiersLoc[SIMPLE];
|
||||
}
|
||||
|
||||
/// Get the second modifier location.
|
||||
SourceLocation getDynGroupprivateFallbackModifierLoc() const {
|
||||
return ModifiersLoc[FALLBACK];
|
||||
}
|
||||
|
||||
/// Get size.
|
||||
Expr *getSize() { return Size; }
|
||||
|
||||
/// Get size.
|
||||
const Expr *getSize() const { return Size; }
|
||||
|
||||
child_range children() {
|
||||
return child_range(reinterpret_cast<Stmt **>(&Size),
|
||||
reinterpret_cast<Stmt **>(&Size) + 1);
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
auto Children = const_cast<OMPDynGroupprivateClause *>(this)->children();
|
||||
return const_child_range(Children.begin(), Children.end());
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == llvm::omp::OMPC_dyn_groupprivate;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents the 'doacross' clause for the '#pragma omp ordered'
|
||||
/// directive.
|
||||
///
|
||||
|
||||
@ -4165,6 +4165,14 @@ bool RecursiveASTVisitor<Derived>::VisitOMPXDynCGroupMemClause(
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPDynGroupprivateClause(
|
||||
OMPDynGroupprivateClause *C) {
|
||||
TRY_TO(VisitOMPClauseWithPreInit(C));
|
||||
TRY_TO(TraverseStmt(C->getSize()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPDoacrossClause(
|
||||
OMPDoacrossClause *C) {
|
||||
|
||||
@ -12137,6 +12137,9 @@ def err_omp_unexpected_schedule_modifier : Error<
|
||||
"modifier '%0' cannot be used along with modifier '%1'">;
|
||||
def err_omp_schedule_nonmonotonic_static : Error<
|
||||
"'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind">;
|
||||
def err_omp_incompatible_dyn_groupprivate_modifier
|
||||
: Error<"modifier '%0' cannot be used along with modifier '%1' in "
|
||||
"dyn_groupprivate">;
|
||||
def err_omp_simple_clause_incompatible_with_ordered : Error<
|
||||
"'%0' clause with '%1' modifier cannot be specified if an 'ordered' clause is specified">;
|
||||
def err_omp_ordered_simd : Error<
|
||||
|
||||
@ -86,6 +86,12 @@
|
||||
#ifndef OPENMP_GRAINSIZE_MODIFIER
|
||||
#define OPENMP_GRAINSIZE_MODIFIER(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DYN_GROUPPRIVATE_MODIFIER
|
||||
#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER
|
||||
#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_NUMTASKS_MODIFIER
|
||||
#define OPENMP_NUMTASKS_MODIFIER(Name)
|
||||
#endif
|
||||
@ -242,6 +248,14 @@ OPENMP_BIND_KIND(thread)
|
||||
// Modifiers for the 'grainsize' clause.
|
||||
OPENMP_GRAINSIZE_MODIFIER(strict)
|
||||
|
||||
// Modifiers for the 'dyn_groupprivate' clause.
|
||||
OPENMP_DYN_GROUPPRIVATE_MODIFIER(cgroup)
|
||||
|
||||
// Fallback modifiers for the 'dyn_groupprivate' clause.
|
||||
OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(abort)
|
||||
OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(null)
|
||||
OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(default_mem)
|
||||
|
||||
// Modifiers for the 'num_tasks' clause.
|
||||
OPENMP_NUMTASKS_MODIFIER(strict)
|
||||
|
||||
@ -263,6 +277,8 @@ OPENMP_THREADSET_KIND(omp_team)
|
||||
|
||||
#undef OPENMP_NUMTASKS_MODIFIER
|
||||
#undef OPENMP_NUMTHREADS_MODIFIER
|
||||
#undef OPENMP_DYN_GROUPPRIVATE_MODIFIER
|
||||
#undef OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER
|
||||
#undef OPENMP_GRAINSIZE_MODIFIER
|
||||
#undef OPENMP_BIND_KIND
|
||||
#undef OPENMP_ADJUST_ARGS_KIND
|
||||
|
||||
@ -224,6 +224,20 @@ enum OpenMPGrainsizeClauseModifier {
|
||||
OMPC_GRAINSIZE_unknown
|
||||
};
|
||||
|
||||
enum OpenMPDynGroupprivateClauseModifier {
|
||||
#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) OMPC_DYN_GROUPPRIVATE_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_DYN_GROUPPRIVATE_unknown
|
||||
};
|
||||
|
||||
enum OpenMPDynGroupprivateClauseFallbackModifier {
|
||||
OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown = OMPC_DYN_GROUPPRIVATE_unknown,
|
||||
#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) \
|
||||
OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_DYN_GROUPPRIVATE_FALLBACK_last
|
||||
};
|
||||
|
||||
enum OpenMPNumTasksClauseModifier {
|
||||
#define OPENMP_NUMTASKS_MODIFIER(Name) OMPC_NUMTASKS_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
|
||||
@ -1411,6 +1411,13 @@ public:
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
/// Called on a well-formed 'dyn_groupprivate' clause.
|
||||
OMPClause *ActOnOpenMPDynGroupprivateClause(
|
||||
OpenMPDynGroupprivateClauseModifier M1,
|
||||
OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
|
||||
SourceLocation M2Loc, SourceLocation EndLoc);
|
||||
|
||||
/// Called on well-formed 'doacross' clause.
|
||||
OMPClause *
|
||||
ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType,
|
||||
|
||||
@ -105,6 +105,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
|
||||
return static_cast<const OMPFilterClause *>(C);
|
||||
case OMPC_ompx_dyn_cgroup_mem:
|
||||
return static_cast<const OMPXDynCGroupMemClause *>(C);
|
||||
case OMPC_dyn_groupprivate:
|
||||
return static_cast<const OMPDynGroupprivateClause *>(C);
|
||||
case OMPC_message:
|
||||
return static_cast<const OMPMessageClause *>(C);
|
||||
case OMPC_default:
|
||||
@ -2857,6 +2859,24 @@ void OMPClausePrinter::VisitOMPXDynCGroupMemClause(
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPDynGroupprivateClause(
|
||||
OMPDynGroupprivateClause *Node) {
|
||||
OS << "dyn_groupprivate(";
|
||||
if (Node->getDynGroupprivateModifier() != OMPC_DYN_GROUPPRIVATE_unknown) {
|
||||
OS << getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate,
|
||||
Node->getDynGroupprivateModifier());
|
||||
if (Node->getDynGroupprivateFallbackModifier() !=
|
||||
OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown) {
|
||||
OS << ", ";
|
||||
OS << getOpenMPSimpleClauseTypeName(
|
||||
OMPC_dyn_groupprivate, Node->getDynGroupprivateFallbackModifier());
|
||||
}
|
||||
OS << ": ";
|
||||
}
|
||||
Node->getSize()->printPretty(OS, nullptr, Policy, 0);
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPDoacrossClause(OMPDoacrossClause *Node) {
|
||||
OS << "doacross(";
|
||||
OpenMPDoacrossClauseModifier DepType = Node->getDependenceType();
|
||||
|
||||
@ -968,6 +968,12 @@ void OMPClauseProfiler::VisitOMPXDynCGroupMemClause(
|
||||
if (Expr *Size = C->getSize())
|
||||
Profiler->VisitStmt(Size);
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPDynGroupprivateClause(
|
||||
const OMPDynGroupprivateClause *C) {
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
if (auto *Size = C->getSize())
|
||||
Profiler->VisitStmt(Size);
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPDoacrossClause(const OMPDoacrossClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
|
||||
@ -196,6 +196,16 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
|
||||
return OMPC_GRAINSIZE_unknown;
|
||||
return Type;
|
||||
}
|
||||
case OMPC_dyn_groupprivate: {
|
||||
return llvm::StringSwitch<unsigned>(Str)
|
||||
#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) \
|
||||
.Case(#Name, OMPC_DYN_GROUPPRIVATE_##Name)
|
||||
#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) \
|
||||
.Case(#Name, OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name) \
|
||||
.Case("fallback(" #Name ")", OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_DYN_GROUPPRIVATE_unknown);
|
||||
}
|
||||
case OMPC_num_tasks: {
|
||||
unsigned Type = llvm::StringSwitch<unsigned>(Str)
|
||||
#define OPENMP_NUMTASKS_MODIFIER(Name) .Case(#Name, OMPC_NUMTASKS_##Name)
|
||||
@ -544,6 +554,20 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'grainsize' clause modifier");
|
||||
case OMPC_dyn_groupprivate:
|
||||
switch (Type) {
|
||||
case OMPC_DYN_GROUPPRIVATE_unknown:
|
||||
case OMPC_DYN_GROUPPRIVATE_FALLBACK_last:
|
||||
return "unknown";
|
||||
#define OPENMP_DYN_GROUPPRIVATE_MODIFIER(Name) \
|
||||
case OMPC_DYN_GROUPPRIVATE_##Name: \
|
||||
return #Name;
|
||||
#define OPENMP_DYN_GROUPPRIVATE_FALLBACK_MODIFIER(Name) \
|
||||
case OMPC_DYN_GROUPPRIVATE_FALLBACK_##Name: \
|
||||
return "fallback(" #Name ")";
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'dyn_groupprivate' clause modifier");
|
||||
case OMPC_num_tasks:
|
||||
switch (Type) {
|
||||
case OMPC_NUMTASKS_unknown:
|
||||
|
||||
@ -3178,6 +3178,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
case OMPC_align:
|
||||
case OMPC_message:
|
||||
case OMPC_ompx_dyn_cgroup_mem:
|
||||
case OMPC_dyn_groupprivate:
|
||||
// OpenMP [2.5, Restrictions]
|
||||
// At most one num_threads clause can appear on the directive.
|
||||
// OpenMP [2.8.1, simd construct, Restrictions]
|
||||
@ -3216,7 +3217,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
|
||||
Clause = ParseOpenMPClause(CKind, WrongDirective);
|
||||
else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
|
||||
CKind == OMPC_num_threads)
|
||||
CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate)
|
||||
Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
|
||||
else
|
||||
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
|
||||
@ -4009,6 +4010,83 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
|
||||
Arg.push_back(OMPC_GRAINSIZE_unknown);
|
||||
KLoc.emplace_back();
|
||||
}
|
||||
} else if (Kind == OMPC_dyn_groupprivate) {
|
||||
enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
|
||||
Arg.resize(NumberOfModifiers);
|
||||
KLoc.resize(NumberOfModifiers);
|
||||
Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
|
||||
Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
|
||||
|
||||
auto ConsumeModifier = [&]() {
|
||||
unsigned Type = NumberOfModifiers;
|
||||
unsigned Modifier;
|
||||
SourceLocation Loc;
|
||||
if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
|
||||
NextToken().is(tok::l_paren)) {
|
||||
ConsumeToken();
|
||||
BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
|
||||
ParenT.consumeOpen();
|
||||
|
||||
Modifier = getOpenMPSimpleClauseType(
|
||||
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
|
||||
if (Modifier <= OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown ||
|
||||
Modifier >= OMPC_DYN_GROUPPRIVATE_FALLBACK_last) {
|
||||
Diag(Tok.getLocation(), diag::err_expected)
|
||||
<< "'abort', 'null' or 'default_mem' in fallback modifier";
|
||||
SkipUntil(tok::r_paren);
|
||||
return std::make_tuple(Type, Modifier, Loc);
|
||||
}
|
||||
Type = ComplexModifier;
|
||||
Loc = Tok.getLocation();
|
||||
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end))
|
||||
ConsumeAnyToken();
|
||||
ParenT.consumeClose();
|
||||
} else {
|
||||
Modifier = getOpenMPSimpleClauseType(
|
||||
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
|
||||
if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
|
||||
Type = SimpleModifier;
|
||||
Loc = Tok.getLocation();
|
||||
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end))
|
||||
ConsumeAnyToken();
|
||||
}
|
||||
}
|
||||
return std::make_tuple(Type, Modifier, Loc);
|
||||
};
|
||||
|
||||
auto SaveModifier = [&](unsigned Type, unsigned Modifier,
|
||||
SourceLocation Loc) {
|
||||
assert(Type < NumberOfModifiers && "Unexpected modifier type");
|
||||
if (!KLoc[Type].isValid()) {
|
||||
Arg[Type] = Modifier;
|
||||
KLoc[Type] = Loc;
|
||||
} else {
|
||||
Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)
|
||||
<< getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Modifier)
|
||||
<< getOpenMPSimpleClauseTypeName(OMPC_dyn_groupprivate, Arg[Type]);
|
||||
}
|
||||
};
|
||||
|
||||
// Parse 'modifier'
|
||||
auto [Type1, Mod1, Loc1] = ConsumeModifier();
|
||||
if (Type1 < NumberOfModifiers) {
|
||||
SaveModifier(Type1, Mod1, Loc1);
|
||||
if (Tok.is(tok::comma)) {
|
||||
// Parse ',' 'modifier'
|
||||
ConsumeAnyToken();
|
||||
auto [Type2, Mod2, Loc2] = ConsumeModifier();
|
||||
if (Type2 < NumberOfModifiers)
|
||||
SaveModifier(Type2, Mod2, Loc2);
|
||||
}
|
||||
// Parse ':'
|
||||
if (Tok.is(tok::colon))
|
||||
ConsumeAnyToken();
|
||||
else
|
||||
Diag(Tok, diag::warn_pragma_expected_colon)
|
||||
<< "dyn_groupprivate modifier";
|
||||
}
|
||||
} else if (Kind == OMPC_num_tasks) {
|
||||
// Parse optional <num_tasks modifier> ':'
|
||||
OpenMPNumTasksClauseModifier Modifier =
|
||||
@ -4083,11 +4161,11 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
|
||||
}
|
||||
}
|
||||
|
||||
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
|
||||
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
|
||||
Kind == OMPC_if || Kind == OMPC_device ||
|
||||
Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
|
||||
Kind == OMPC_num_threads;
|
||||
bool NeedAnExpression =
|
||||
(Kind == OMPC_schedule && DelimLoc.isValid()) ||
|
||||
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||
|
||||
Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
|
||||
Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;
|
||||
if (NeedAnExpression) {
|
||||
SourceLocation ELoc = Tok.getLocation();
|
||||
ExprResult LHS(
|
||||
|
||||
@ -16532,6 +16532,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
||||
case OMPC_holds:
|
||||
Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_dyn_groupprivate:
|
||||
case OMPC_grainsize:
|
||||
case OMPC_num_tasks:
|
||||
case OMPC_num_threads:
|
||||
@ -16658,6 +16659,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
|
||||
case OMPC_num_teams:
|
||||
case OMPC_thread_limit:
|
||||
case OMPC_ompx_dyn_cgroup_mem:
|
||||
case OMPC_dyn_groupprivate:
|
||||
// TODO: This may need to consider teams too.
|
||||
if (Leafs[0] == OMPD_target)
|
||||
return OMPD_target;
|
||||
break;
|
||||
@ -17705,7 +17708,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
|
||||
SourceLocation EndLoc) {
|
||||
OMPClause *Res = nullptr;
|
||||
switch (Kind) {
|
||||
case OMPC_schedule:
|
||||
case OMPC_schedule: {
|
||||
enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
|
||||
assert(Argument.size() == NumberOfElements &&
|
||||
ArgumentLoc.size() == NumberOfElements);
|
||||
@ -17716,6 +17719,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
|
||||
StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
|
||||
ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
|
||||
break;
|
||||
}
|
||||
case OMPC_if:
|
||||
assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
|
||||
Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
|
||||
@ -17771,6 +17775,20 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause(
|
||||
static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
|
||||
StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
|
||||
break;
|
||||
case OMPC_dyn_groupprivate: {
|
||||
enum { Modifier1, Modifier2, NumberOfElements };
|
||||
assert(Argument.size() == NumberOfElements &&
|
||||
ArgumentLoc.size() == NumberOfElements &&
|
||||
"Modifiers for dyn_groupprivate clause and their locations are "
|
||||
"expected.");
|
||||
Res = ActOnOpenMPDynGroupprivateClause(
|
||||
static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
|
||||
static_cast<OpenMPDynGroupprivateClauseFallbackModifier>(
|
||||
Argument[Modifier2]),
|
||||
Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
|
||||
ArgumentLoc[Modifier2], EndLoc);
|
||||
break;
|
||||
}
|
||||
case OMPC_num_threads:
|
||||
assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
|
||||
"Modifier for num_threads clause and its location are expected.");
|
||||
@ -18127,6 +18145,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPClause(OpenMPClauseKind Kind,
|
||||
case OMPC_affinity:
|
||||
case OMPC_when:
|
||||
case OMPC_ompx_dyn_cgroup_mem:
|
||||
case OMPC_dyn_groupprivate:
|
||||
default:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
}
|
||||
@ -25246,6 +25265,49 @@ OMPClause *SemaOpenMP::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
|
||||
ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *SemaOpenMP::ActOnOpenMPDynGroupprivateClause(
|
||||
OpenMPDynGroupprivateClauseModifier M1,
|
||||
OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
|
||||
SourceLocation M2Loc, SourceLocation EndLoc) {
|
||||
|
||||
if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
|
||||
(M2Loc.isValid() && M2 == OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown)) {
|
||||
std::string Values = getListOfPossibleValues(
|
||||
OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
|
||||
Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
|
||||
: M2Loc,
|
||||
diag::err_omp_unexpected_clause_value)
|
||||
<< Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Expr *ValExpr = Size;
|
||||
Stmt *HelperValStmt = nullptr;
|
||||
|
||||
// OpenMP [2.5, Restrictions]
|
||||
// The dyn_groupprivate expression must evaluate to a positive integer
|
||||
// value.
|
||||
if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
|
||||
/*StrictlyPositive=*/false))
|
||||
return nullptr;
|
||||
|
||||
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
|
||||
OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
|
||||
DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP);
|
||||
if (CaptureRegion != OMPD_unknown &&
|
||||
!SemaRef.CurContext->isDependentContext()) {
|
||||
ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
|
||||
llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
|
||||
ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
|
||||
HelperValStmt = buildPreInits(getASTContext(), Captures);
|
||||
}
|
||||
|
||||
return new (getASTContext()) OMPDynGroupprivateClause(
|
||||
StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
|
||||
M1Loc, M2, M2Loc);
|
||||
}
|
||||
|
||||
OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
|
||||
OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
|
||||
SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
|
||||
|
||||
@ -2463,6 +2463,19 @@ public:
|
||||
LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// Build a new OpenMP 'dyn_groupprivate' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPDynGroupprivateClause(
|
||||
OpenMPDynGroupprivateClauseModifier M1,
|
||||
OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
|
||||
SourceLocation M2Loc, SourceLocation EndLoc) {
|
||||
return getSema().OpenMP().ActOnOpenMPDynGroupprivateClause(
|
||||
M1, M2, Size, StartLoc, LParenLoc, M1Loc, M2Loc, EndLoc);
|
||||
}
|
||||
|
||||
/// Build a new OpenMP 'ompx_attribute' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
@ -11725,6 +11738,19 @@ OMPClause *TreeTransform<Derived>::TransformOMPXDynCGroupMemClause(
|
||||
Size.get(), C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *TreeTransform<Derived>::TransformOMPDynGroupprivateClause(
|
||||
OMPDynGroupprivateClause *C) {
|
||||
ExprResult Size = getDerived().TransformExpr(C->getSize());
|
||||
if (Size.isInvalid())
|
||||
return nullptr;
|
||||
return getDerived().RebuildOMPDynGroupprivateClause(
|
||||
C->getDynGroupprivateModifier(), C->getDynGroupprivateFallbackModifier(),
|
||||
Size.get(), C->getBeginLoc(), C->getLParenLoc(),
|
||||
C->getDynGroupprivateModifierLoc(),
|
||||
C->getDynGroupprivateFallbackModifierLoc(), C->getEndLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPDoacrossClause(OMPDoacrossClause *C) {
|
||||
|
||||
@ -11544,6 +11544,9 @@ OMPClause *OMPClauseReader::readClause() {
|
||||
case llvm::omp::OMPC_ompx_dyn_cgroup_mem:
|
||||
C = new (Context) OMPXDynCGroupMemClause();
|
||||
break;
|
||||
case llvm::omp::OMPC_dyn_groupprivate:
|
||||
C = new (Context) OMPDynGroupprivateClause();
|
||||
break;
|
||||
case llvm::omp::OMPC_doacross: {
|
||||
unsigned NumVars = Record.readInt();
|
||||
unsigned NumLoops = Record.readInt();
|
||||
@ -12736,6 +12739,19 @@ void OMPClauseReader::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) {
|
||||
C->setLParenLoc(Record.readSourceLocation());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPDynGroupprivateClause(
|
||||
OMPDynGroupprivateClause *C) {
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
C->setDynGroupprivateModifier(
|
||||
Record.readEnum<OpenMPDynGroupprivateClauseModifier>());
|
||||
C->setDynGroupprivateFallbackModifier(
|
||||
Record.readEnum<OpenMPDynGroupprivateClauseFallbackModifier>());
|
||||
C->setSize(Record.readSubExpr());
|
||||
C->setLParenLoc(Record.readSourceLocation());
|
||||
C->setDynGroupprivateModifierLoc(Record.readSourceLocation());
|
||||
C->setDynGroupprivateFallbackModifierLoc(Record.readSourceLocation());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPDoacrossClause(OMPDoacrossClause *C) {
|
||||
C->setLParenLoc(Record.readSourceLocation());
|
||||
C->setDependenceType(
|
||||
|
||||
@ -8651,6 +8651,17 @@ void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) {
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPDynGroupprivateClause(
|
||||
OMPDynGroupprivateClause *C) {
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
Record.push_back(C->getDynGroupprivateModifier());
|
||||
Record.push_back(C->getDynGroupprivateFallbackModifier());
|
||||
Record.AddStmt(C->getSize());
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
Record.AddSourceLocation(C->getDynGroupprivateModifierLoc());
|
||||
Record.AddSourceLocation(C->getDynGroupprivateFallbackModifierLoc());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPDoacrossClause(OMPDoacrossClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Record.push_back(C->getNumLoops());
|
||||
|
||||
89
clang/test/OpenMP/target_dyn_groupprivate_messages.cpp
Normal file
89
clang/test/OpenMP/target_dyn_groupprivate_messages.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=61 %s -Wuninitialized
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}}
|
||||
|
||||
template <class T, class S> // expected-note {{declared here}}
|
||||
int tmain(T argc, S **argv) {
|
||||
T z;
|
||||
#pragma omp target dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate () // expected-error {{expected expression}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp target' cannot contain more than one 'dyn_groupprivate' clause}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (S) // expected-error {{'S' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(argc+z)
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
constexpr int n = -1;
|
||||
int z;
|
||||
#pragma omp target dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate () // expected-error {{expected expression}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target' are ignored}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp target' cannot contain more than one 'dyn_groupprivate' clause}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (S1) // expected-error {{'S1' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(dyn_groupprivate(tmain(argc, argv) // expected-error2 {{expected ')'}} expected-note2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(-1) // expected-error {{argument to 'dyn_groupprivate' clause must be a non-negative integer value}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(cgrou) // expected-error {{use of undeclared identifier 'cgrou'}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(cgrou: argc) // expected-error {{use of undeclared identifier 'cgrou'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(cgroup,cgroup: argc) // expected-error {{modifier 'cgroup' cannot be used along with modifier 'cgroup' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(default_mem),fallback(abort): argc) // expected-error {{modifier 'fallback(abort)' cannot be used along with modifier 'fallback(default_mem)' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(abort),fallback(null): argc) // expected-error {{modifier 'fallback(null)' cannot be used along with modifier 'fallback(abort)' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(cgroup): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(: argc) // expected-error {{expected ')'}} expected-error {{expected expression}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
|
||||
return tmain(argc, argv);
|
||||
}
|
||||
|
||||
89
clang/test/OpenMP/target_teams_dyn_groupprivate_messages.cpp
Normal file
89
clang/test/OpenMP/target_teams_dyn_groupprivate_messages.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=61 %s -Wuninitialized
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}}
|
||||
|
||||
template <class T, class S> // expected-note {{declared here}}
|
||||
int tmain(T argc, S **argv) {
|
||||
T z;
|
||||
#pragma omp target teams dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate () // expected-error {{expected expression}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'dyn_groupprivate' clause}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (S) // expected-error {{'S' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate(argc+z)
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
constexpr int n = -1;
|
||||
int z;
|
||||
#pragma omp target teams dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate () // expected-error {{expected expression}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target teams' are ignored}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'dyn_groupprivate' clause}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (S1) // expected-error {{'S1' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate(dyn_groupprivate(tmain(argc, argv) // expected-error2 {{expected ')'}} expected-note2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate(-1) // expected-error {{argument to 'dyn_groupprivate' clause must be a non-negative integer value}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate(cgrou) // expected-error {{use of undeclared identifier 'cgrou'}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate(cgrou: argc) // expected-error {{use of undeclared identifier 'cgrou'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate(cgroup,cgroup: argc) // expected-error {{modifier 'cgroup' cannot be used along with modifier 'cgroup' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(default_mem),fallback(abort): argc) // expected-error {{modifier 'fallback(abort)' cannot be used along with modifier 'fallback(default_mem)' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(abort),fallback(null): argc) // expected-error {{modifier 'fallback(null)' cannot be used along with modifier 'fallback(abort)' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(cgroup): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target teams dyn_groupprivate(: argc) // expected-error {{expected ')'}} expected-error {{expected expression}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
|
||||
return tmain(argc, argv);
|
||||
}
|
||||
|
||||
89
clang/test/OpenMP/teams_dyn_groupprivate_messages.cpp
Normal file
89
clang/test/OpenMP/teams_dyn_groupprivate_messages.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=61 %s -Wuninitialized
|
||||
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=61 %s -Wuninitialized
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}}
|
||||
|
||||
template <class T, class S> // expected-note {{declared here}}
|
||||
int tmain(T argc, S **argv) {
|
||||
T z;
|
||||
#pragma omp teams dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate () // expected-error {{expected expression}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams' are ignored}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp teams' cannot contain more than one 'dyn_groupprivate' clause}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (S) // expected-error {{'S' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate(argc+z)
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
constexpr int n = -1;
|
||||
int z;
|
||||
#pragma omp teams dyn_groupprivate // expected-error {{expected '(' after 'dyn_groupprivate'}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate () // expected-error {{expected expression}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argc)) // expected-warning {{extra tokens at the end of '#pragma omp teams' are ignored}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (foobool(argc)), dyn_groupprivate (true) // expected-error {{directive '#pragma omp teams' cannot contain more than one 'dyn_groupprivate' clause}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (S1) // expected-error {{'S1' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argv[1]=2) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate(dyn_groupprivate(tmain(argc, argv) // expected-error2 {{expected ')'}} expected-note2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate(-1) // expected-error {{argument to 'dyn_groupprivate' clause must be a non-negative integer value}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate(cgrou) // expected-error {{use of undeclared identifier 'cgrou'}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate(cgrou: argc) // expected-error {{use of undeclared identifier 'cgrou'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate(cgroup,cgroup: argc) // expected-error {{modifier 'cgroup' cannot be used along with modifier 'cgroup' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(default_mem),fallback(abort): argc) // expected-error {{modifier 'fallback(abort)' cannot be used along with modifier 'fallback(default_mem)' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(abort),fallback(null): argc) // expected-error {{modifier 'fallback(null)' cannot be used along with modifier 'fallback(abort)' in dyn_groupprivate}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(cgroup): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp target dyn_groupprivate(fallback(): argc) // expected-error {{expected 'abort', 'null' or 'default_mem' in fallback modifier}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp teams dyn_groupprivate(: argc) // expected-error {{expected ')'}} expected-error {{expected expression}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
|
||||
return tmain(argc, argv);
|
||||
}
|
||||
|
||||
@ -2757,6 +2757,11 @@ void OMPClauseEnqueue::VisitOMPXDynCGroupMemClause(
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
Visitor->AddStmt(C->getSize());
|
||||
}
|
||||
void OMPClauseEnqueue::VisitOMPDynGroupprivateClause(
|
||||
const OMPDynGroupprivateClause *C) {
|
||||
VisitOMPClauseWithPreInit(C);
|
||||
Visitor->AddStmt(C->getSize());
|
||||
}
|
||||
void OMPClauseEnqueue::VisitOMPDoacrossClause(const OMPDoacrossClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
|
||||
@ -187,6 +187,7 @@ def OMPC_DynamicAllocators : Clause<[Spelling<"dynamic_allocators">]> {
|
||||
let isValueOptional = true;
|
||||
}
|
||||
def OMPC_DynGroupprivate : Clause<[Spelling<"dyn_groupprivate">]> {
|
||||
let clangClass = "OMPDynGroupprivateClause";
|
||||
let flangClass = "OmpDynGroupprivateClause";
|
||||
}
|
||||
def OMPC_Enter : Clause<[Spelling<"enter">]> {
|
||||
|
||||
@ -88,6 +88,7 @@ using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>;
|
||||
using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>;
|
||||
using DynamicAllocators =
|
||||
tomp::clause::DynamicAllocatorsT<TypeTy, IdTy, ExprTy>;
|
||||
using DynGroupprivate = tomp::clause::DynGroupprivateT<TypeTy, IdTy, ExprTy>;
|
||||
using Enter = tomp::clause::EnterT<TypeTy, IdTy, ExprTy>;
|
||||
using Exclusive = tomp::clause::ExclusiveT<TypeTy, IdTy, ExprTy>;
|
||||
using Fail = tomp::clause::FailT<TypeTy, IdTy, ExprTy>;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user