[OPENMP]Initial support for at clause
Error directive is allowed in both declared and executable contexts. The function ActOnOpenMPAtClause is called in both places during the parsers. Adding a param "bool InExContext" to identify context which is used to emit error massage. Differential Revision: https://reviews.llvm.org/D137851
This commit is contained in:
parent
05ec16d90d
commit
628fdc3f57
@ -1563,6 +1563,85 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents 'at' clause in the '#pragma omp error' directive
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp error at(compilation)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp error' has simple
|
||||
/// 'at' clause with kind 'complilation'.
|
||||
class OMPAtClause final : public OMPClause {
|
||||
friend class OMPClauseReader;
|
||||
|
||||
/// Location of '('
|
||||
SourceLocation LParenLoc;
|
||||
|
||||
/// A kind of the 'at' clause.
|
||||
OpenMPAtClauseKind Kind = OMPC_AT_unknown;
|
||||
|
||||
/// Start location of the kind in source code.
|
||||
SourceLocation KindKwLoc;
|
||||
|
||||
/// Set kind of the clause.
|
||||
///
|
||||
/// \param K Kind of clause.
|
||||
void setAtKind(OpenMPAtClauseKind K) { Kind = K; }
|
||||
|
||||
/// Set clause kind location.
|
||||
///
|
||||
/// \param KLoc Kind location.
|
||||
void setAtKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
|
||||
|
||||
/// Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
|
||||
public:
|
||||
/// Build 'at' clause with argument \a A ('compilation' or 'execution').
|
||||
///
|
||||
/// \param A Argument of the clause ('compilation' or 'execution').
|
||||
/// \param ALoc Starting location of the argument.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPAtClause(OpenMPAtClauseKind A, SourceLocation ALoc,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(llvm::omp::OMPC_at, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Kind(A), KindKwLoc(ALoc) {}
|
||||
|
||||
/// Build an empty clause.
|
||||
OMPAtClause()
|
||||
: OMPClause(llvm::omp::OMPC_at, SourceLocation(), SourceLocation()) {}
|
||||
|
||||
/// Returns the locaiton of '('.
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
|
||||
/// Returns kind of the clause.
|
||||
OpenMPAtClauseKind getAtKind() const { return Kind; }
|
||||
|
||||
/// Returns location of clause kind.
|
||||
SourceLocation getAtKindKwLoc() const { return KindKwLoc; }
|
||||
|
||||
child_range children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
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_at;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents 'schedule' clause in the '#pragma omp ...' directive.
|
||||
///
|
||||
/// \code
|
||||
|
||||
@ -3310,6 +3310,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAtomicDefaultMemOrderClause(
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPAtClause(OMPAtClause *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
|
||||
@ -1401,6 +1401,8 @@ def err_omp_mapper_expected_declarator : Error<
|
||||
"expected declarator on 'omp declare mapper' directive">;
|
||||
def err_omp_unexpected_append_op : Error<
|
||||
"unexpected operation specified in 'append_args' clause, expected 'interop'">;
|
||||
def err_omp_unexpected_execution_modifier : Error<
|
||||
"unexpected 'execution' modifier in non-executable context">;
|
||||
def err_omp_declare_variant_wrong_clause : Error<
|
||||
"expected %select{'match'|'match', 'adjust_args', or 'append_args'}0 clause "
|
||||
"on 'omp declare variant' directive">;
|
||||
|
||||
@ -41,6 +41,9 @@
|
||||
#ifndef OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND
|
||||
#define OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_AT_KIND
|
||||
#define OPENMP_AT_KIND(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DEFAULTMAP_MODIFIER
|
||||
#define OPENMP_DEFAULTMAP_MODIFIER(Name)
|
||||
#endif
|
||||
@ -119,6 +122,10 @@ OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(seq_cst)
|
||||
OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(acq_rel)
|
||||
OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND(relaxed)
|
||||
|
||||
// Modifiers for 'at' clause.
|
||||
OPENMP_AT_KIND(compilation)
|
||||
OPENMP_AT_KIND(execution)
|
||||
|
||||
// Map types for 'map' clause.
|
||||
OPENMP_MAP_KIND(alloc)
|
||||
OPENMP_MAP_KIND(to)
|
||||
@ -179,6 +186,7 @@ OPENMP_BIND_KIND(thread)
|
||||
#undef OPENMP_SCHEDULE_MODIFIER
|
||||
#undef OPENMP_SCHEDULE_KIND
|
||||
#undef OPENMP_ATOMIC_DEFAULT_MEM_ORDER_KIND
|
||||
#undef OPENMP_AT_KIND
|
||||
#undef OPENMP_MAP_KIND
|
||||
#undef OPENMP_MAP_MODIFIER_KIND
|
||||
#undef OPENMP_MOTION_MODIFIER_KIND
|
||||
|
||||
@ -131,6 +131,13 @@ enum OpenMPAtomicDefaultMemOrderClauseKind {
|
||||
OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
|
||||
};
|
||||
|
||||
/// OpenMP attributes for 'at' clause.
|
||||
enum OpenMPAtClauseKind {
|
||||
#define OPENMP_AT_KIND(Name) OMPC_AT_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_AT_unknown
|
||||
};
|
||||
|
||||
/// OpenMP device type for 'device_type' clause.
|
||||
enum OpenMPDeviceType {
|
||||
#define OPENMP_DEVICE_TYPE_KIND(Name) \
|
||||
|
||||
@ -3293,6 +3293,15 @@ private:
|
||||
/// Parse 'omp end assumes' directive.
|
||||
void ParseOpenMPEndAssumesDirective(SourceLocation Loc);
|
||||
|
||||
/// Parses clauses for directive.
|
||||
///
|
||||
/// \param DKind Kind of current directive.
|
||||
/// \param clauses for current directive.
|
||||
/// \param start location for clauses of current directive
|
||||
void ParseOpenMPClauses(OpenMPDirectiveKind DKind,
|
||||
SmallVectorImpl<clang::OMPClause *> &Clauses,
|
||||
SourceLocation Loc);
|
||||
|
||||
/// Parse clauses for '#pragma omp [begin] declare target'.
|
||||
void ParseOMPDeclareTargetClauses(Sema::DeclareTargetContextInfo &DTCI);
|
||||
|
||||
|
||||
@ -11287,9 +11287,12 @@ public:
|
||||
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// Called on well-formed '\#pragma omp error'.
|
||||
/// Error direcitive is allowed in both declared and excutable contexts.
|
||||
/// Adding InExContext to identify which context is called from.
|
||||
StmtResult ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
SourceLocation EndLoc,
|
||||
bool InExContext = true);
|
||||
/// Called on well-formed '\#pragma omp barrier'.
|
||||
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
@ -11826,6 +11829,13 @@ public:
|
||||
OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
|
||||
|
||||
/// Called on well-formed 'at' clause.
|
||||
OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
|
||||
SourceLocation KindLoc,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
/// Data used for processing a list of variables in OpenMP clauses.
|
||||
struct OpenMPVarListDataTy final {
|
||||
Expr *DepModOrTailExpr = nullptr;
|
||||
|
||||
@ -152,6 +152,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
|
||||
case OMPC_reverse_offload:
|
||||
case OMPC_dynamic_allocators:
|
||||
case OMPC_atomic_default_mem_order:
|
||||
case OMPC_at:
|
||||
case OMPC_device_type:
|
||||
case OMPC_match:
|
||||
case OMPC_nontemporal:
|
||||
@ -251,6 +252,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
|
||||
case OMPC_reverse_offload:
|
||||
case OMPC_dynamic_allocators:
|
||||
case OMPC_atomic_default_mem_order:
|
||||
case OMPC_at:
|
||||
case OMPC_device_type:
|
||||
case OMPC_match:
|
||||
case OMPC_nontemporal:
|
||||
@ -1781,6 +1783,11 @@ void OMPClausePrinter::VisitOMPAtomicDefaultMemOrderClause(
|
||||
<< ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPAtClause(OMPAtClause *Node) {
|
||||
OS << "at(" << getOpenMPSimpleClauseTypeName(OMPC_at, Node->getAtKind())
|
||||
<< ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
|
||||
OS << "schedule(";
|
||||
if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
|
||||
|
||||
@ -530,6 +530,8 @@ void OMPClauseProfiler::VisitOMPDynamicAllocatorsClause(
|
||||
void OMPClauseProfiler::VisitOMPAtomicDefaultMemOrderClause(
|
||||
const OMPAtomicDefaultMemOrderClause *C) {}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPAtClause(const OMPAtClause *C) {}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPScheduleClause(const OMPScheduleClause *C) {
|
||||
VistOMPClauseWithPreInit(C);
|
||||
if (auto *S = C->getChunkSize())
|
||||
|
||||
@ -104,6 +104,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
|
||||
#define OPENMP_DEVICE_TYPE_KIND(Name) .Case(#Name, OMPC_DEVICE_TYPE_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_DEVICE_TYPE_unknown);
|
||||
case OMPC_at:
|
||||
return llvm::StringSwitch<OpenMPAtClauseKind>(Str)
|
||||
#define OPENMP_AT_KIND(Name) .Case(#Name, OMPC_AT_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_AT_unknown);
|
||||
case OMPC_lastprivate:
|
||||
return llvm::StringSwitch<OpenMPLastprivateModifier>(Str)
|
||||
#define OPENMP_LASTPRIVATE_KIND(Name) .Case(#Name, OMPC_LASTPRIVATE_##Name)
|
||||
@ -336,6 +341,17 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'device_type' clause type");
|
||||
case OMPC_at:
|
||||
switch (Type) {
|
||||
case OMPC_AT_unknown:
|
||||
return "unknown";
|
||||
#define OPENMP_AT_KIND(Name) \
|
||||
case OMPC_AT_##Name: \
|
||||
return #Name;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'at' clause type");
|
||||
llvm_unreachable("Invalid OpenMP 'at' clause type");
|
||||
case OMPC_lastprivate:
|
||||
switch (Type) {
|
||||
case OMPC_LASTPRIVATE_unknown:
|
||||
|
||||
@ -6512,6 +6512,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
|
||||
case OMPC_reverse_offload:
|
||||
case OMPC_dynamic_allocators:
|
||||
case OMPC_atomic_default_mem_order:
|
||||
case OMPC_at:
|
||||
case OMPC_device_type:
|
||||
case OMPC_match:
|
||||
case OMPC_nontemporal:
|
||||
|
||||
@ -1627,6 +1627,42 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <clause> [clause[ [,] clause] ... ]
|
||||
///
|
||||
/// clauses: for error directive
|
||||
/// 'at' '(' compilation | execution ')'
|
||||
/// 'severity' '(' fatal | warning ')'
|
||||
/// 'message' '(' msg-string ')'
|
||||
/// ....
|
||||
void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
|
||||
SmallVectorImpl<OMPClause *> &Clauses,
|
||||
SourceLocation Loc) {
|
||||
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
|
||||
llvm::omp::Clause_enumSize + 1>
|
||||
FirstClauses(llvm::omp::Clause_enumSize + 1);
|
||||
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||
OpenMPClauseKind CKind = Tok.isAnnotation()
|
||||
? OMPC_unknown
|
||||
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
||||
Actions.StartOpenMPClause(CKind);
|
||||
OMPClause *Clause = ParseOpenMPClause(
|
||||
DKind, CKind, !FirstClauses[unsigned(CKind)].getInt());
|
||||
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
|
||||
StopBeforeMatch);
|
||||
FirstClauses[unsigned(CKind)].setInt(true);
|
||||
if (Clause != nullptr)
|
||||
Clauses.push_back(Clause);
|
||||
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
||||
Actions.EndOpenMPClause();
|
||||
break;
|
||||
}
|
||||
// Skip ',' if any.
|
||||
if (Tok.is(tok::comma))
|
||||
ConsumeToken();
|
||||
Actions.EndOpenMPClause();
|
||||
}
|
||||
}
|
||||
|
||||
/// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
|
||||
/// where
|
||||
///
|
||||
@ -2124,6 +2160,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||
ConsumeAnnotationToken();
|
||||
return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
|
||||
}
|
||||
case OMPD_error: {
|
||||
SmallVector<OMPClause *, 1> Clauses;
|
||||
SourceLocation StartLoc = ConsumeToken();
|
||||
ParseOpenMPClauses(DKind, Clauses, StartLoc);
|
||||
Actions.ActOnOpenMPErrorDirective(Clauses, StartLoc, SourceLocation(),
|
||||
/*InExContext = */ false);
|
||||
break;
|
||||
}
|
||||
case OMPD_assumes:
|
||||
case OMPD_begin_assumes:
|
||||
ParseOpenMPAssumesDirective(DKind, ConsumeToken());
|
||||
@ -2310,7 +2354,6 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
||||
case OMPD_unroll:
|
||||
case OMPD_task:
|
||||
case OMPD_taskyield:
|
||||
case OMPD_error:
|
||||
case OMPD_barrier:
|
||||
case OMPD_taskwait:
|
||||
case OMPD_taskgroup:
|
||||
@ -2711,6 +2754,10 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
|
||||
ParsedStmtContext()) {
|
||||
Diag(Tok, diag::err_omp_immediate_directive)
|
||||
<< getOpenMPDirectiveName(DKind) << 0;
|
||||
if (DKind == OMPD_error) {
|
||||
SkipUntil(tok::annot_pragma_openmp_end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
HasAssociatedStatement = false;
|
||||
// Fall through for further analysis.
|
||||
@ -3170,6 +3217,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
case OMPC_default:
|
||||
case OMPC_proc_bind:
|
||||
case OMPC_atomic_default_mem_order:
|
||||
case OMPC_at:
|
||||
case OMPC_order:
|
||||
case OMPC_bind:
|
||||
// OpenMP [2.14.3.1, Restrictions]
|
||||
@ -3180,6 +3228,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
// OpenMP [5.0, Requires directive, Restrictions]
|
||||
// At most one atomic_default_mem_order clause can appear
|
||||
// on the directive
|
||||
// OpenMP [5.1, Requires directive, Restrictions]
|
||||
// At most one at clause can appear on the directive
|
||||
// OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
|
||||
// At most one bind clause can appear on a loop directive.
|
||||
if (!FirstClause && CKind != OMPC_order) {
|
||||
|
||||
@ -6308,7 +6308,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
|
||||
break;
|
||||
case OMPD_error:
|
||||
assert(AStmt == nullptr &&
|
||||
"No associated statement allowed for 'omp taskyield' directive");
|
||||
"No associated statement allowed for 'omp error' directive");
|
||||
Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
|
||||
break;
|
||||
case OMPD_barrier:
|
||||
@ -6719,6 +6719,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
|
||||
case OMPC_device_type:
|
||||
case OMPC_match:
|
||||
case OMPC_when:
|
||||
case OMPC_at:
|
||||
default:
|
||||
llvm_unreachable("Unexpected clause");
|
||||
}
|
||||
@ -11028,7 +11029,21 @@ StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
|
||||
|
||||
StmtResult Sema::ActOnOpenMPErrorDirective(ArrayRef<OMPClause *> Clauses,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
SourceLocation EndLoc,
|
||||
bool InExContext) {
|
||||
auto AtClauses =
|
||||
OMPExecutableDirective::getClausesOfKind<OMPAtClause>(Clauses);
|
||||
const OMPAtClause *AtC = AtClauses.empty() ? nullptr : (*AtClauses.begin());
|
||||
|
||||
if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
|
||||
Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
|
||||
return StmtError();
|
||||
}
|
||||
if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
|
||||
Diag(AtC ? AtC->getBeginLoc() : StartLoc, diag::err_diagnose_if_succeeded)
|
||||
<< "ERROR";
|
||||
return StmtError();
|
||||
}
|
||||
return OMPErrorDirective::Create(Context, StartLoc, EndLoc, Clauses);
|
||||
}
|
||||
|
||||
@ -15171,6 +15186,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
|
||||
case OMPC_match:
|
||||
case OMPC_nontemporal:
|
||||
case OMPC_order:
|
||||
case OMPC_at:
|
||||
case OMPC_destroy:
|
||||
case OMPC_inclusive:
|
||||
case OMPC_exclusive:
|
||||
@ -16096,6 +16112,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
|
||||
case OMPC_match:
|
||||
case OMPC_nontemporal:
|
||||
case OMPC_order:
|
||||
case OMPC_at:
|
||||
case OMPC_destroy:
|
||||
case OMPC_detach:
|
||||
case OMPC_inclusive:
|
||||
@ -16498,6 +16515,10 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
|
||||
Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
|
||||
ArgumentLoc, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_at:
|
||||
Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
|
||||
ArgumentLoc, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_if:
|
||||
case OMPC_final:
|
||||
case OMPC_num_threads:
|
||||
@ -16676,6 +16697,22 @@ OMPClause *Sema::ActOnOpenMPAtomicDefaultMemOrderClause(
|
||||
LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
|
||||
SourceLocation KindKwLoc,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
if (Kind == OMPC_AT_unknown) {
|
||||
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
|
||||
<< getListOfPossibleValues(OMPC_at, /*First=*/0,
|
||||
/*Last=*/OMPC_AT_unknown)
|
||||
<< getOpenMPClauseName(OMPC_at);
|
||||
return nullptr;
|
||||
}
|
||||
return new (Context)
|
||||
OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPOrderClause(OpenMPOrderClauseKind Kind,
|
||||
SourceLocation KindKwLoc,
|
||||
SourceLocation StartLoc,
|
||||
@ -16875,6 +16912,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
|
||||
case OMPC_match:
|
||||
case OMPC_nontemporal:
|
||||
case OMPC_order:
|
||||
case OMPC_at:
|
||||
case OMPC_destroy:
|
||||
case OMPC_novariants:
|
||||
case OMPC_nocontext:
|
||||
@ -17131,6 +17169,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
|
||||
case OMPC_match:
|
||||
case OMPC_nontemporal:
|
||||
case OMPC_order:
|
||||
case OMPC_at:
|
||||
case OMPC_novariants:
|
||||
case OMPC_nocontext:
|
||||
case OMPC_detach:
|
||||
@ -17685,6 +17724,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
||||
case OMPC_device_type:
|
||||
case OMPC_match:
|
||||
case OMPC_order:
|
||||
case OMPC_at:
|
||||
case OMPC_destroy:
|
||||
case OMPC_novariants:
|
||||
case OMPC_nocontext:
|
||||
|
||||
@ -2351,6 +2351,17 @@ public:
|
||||
return getSema().ActOnOpenMPAlignClause(A, StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// Build a new OpenMP 'at' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KwLoc,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPAtClause(Kind, KwLoc, StartLoc, LParenLoc,
|
||||
EndLoc);
|
||||
}
|
||||
/// Rebuild the operand to an Objective-C \@synchronized statement.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
@ -9855,6 +9866,13 @@ OMPClause *TreeTransform<Derived>::TransformOMPAtomicDefaultMemOrderClause(
|
||||
"atomic_default_mem_order clause cannot appear in dependent context");
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *TreeTransform<Derived>::TransformOMPAtClause(OMPAtClause *C) {
|
||||
return getDerived().RebuildOMPAtClause(C->getAtKind(), C->getAtKindKwLoc(),
|
||||
C->getBeginLoc(), C->getLParenLoc(),
|
||||
C->getEndLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
|
||||
|
||||
@ -9934,7 +9934,10 @@ OMPClause *OMPClauseReader::readClause() {
|
||||
case llvm::omp::OMPC_atomic_default_mem_order:
|
||||
C = new (Context) OMPAtomicDefaultMemOrderClause();
|
||||
break;
|
||||
case llvm::omp::OMPC_private:
|
||||
case llvm::omp::OMPC_at:
|
||||
C = new (Context) OMPAtClause();
|
||||
break;
|
||||
case llvm::omp::OMPC_private:
|
||||
C = OMPPrivateClause::CreateEmpty(Context, Record.readInt());
|
||||
break;
|
||||
case llvm::omp::OMPC_firstprivate:
|
||||
@ -10336,6 +10339,12 @@ void OMPClauseReader::VisitOMPAtomicDefaultMemOrderClause(
|
||||
C->setAtomicDefaultMemOrderKindKwLoc(Record.readSourceLocation());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPAtClause(OMPAtClause *C) {
|
||||
C->setAtKind(static_cast<OpenMPAtClauseKind>(Record.readInt()));
|
||||
C->setLParenLoc(Record.readSourceLocation());
|
||||
C->setAtKindKwLoc(Record.readSourceLocation());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
||||
C->setLParenLoc(Record.readSourceLocation());
|
||||
unsigned NumVars = C->varlist_size();
|
||||
|
||||
@ -6981,6 +6981,12 @@ void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause(
|
||||
Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPAtClause(OMPAtClause *C) {
|
||||
Record.push_back(C->getAtKind());
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
Record.AddSourceLocation(C->getAtKindKwLoc());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
|
||||
@ -13,16 +13,16 @@
|
||||
void foo() {}
|
||||
// CHECK: template <typename T, int N> int tmain(T argc, char **argv)
|
||||
// CHECK: static int a;
|
||||
// CHECK-NEXT: #pragma omp error
|
||||
// CHECK-NEXT: #pragma omp error at(execution)
|
||||
// CHECK-NEXT: a = argv[0][0];
|
||||
// CHECK-NEXT: ++a;
|
||||
// CHECK-NEXT: #pragma omp error
|
||||
// CHECK-NEXT: #pragma omp error at(execution)
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: int b = 10;
|
||||
// CHECK-NEXT: T c = 100;
|
||||
// CHECK-NEXT: a = b + c;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: #pragma omp error
|
||||
// CHECK-NEXT: #pragma omp error at(execution)
|
||||
// CHECK-NEXT: foo();
|
||||
// CHECK-NEXT: return N;
|
||||
|
||||
@ -30,16 +30,16 @@ template <typename T, int N>
|
||||
int tmain(T argc, char **argv) {
|
||||
T b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
#pragma omp error
|
||||
#pragma omp error at(execution)
|
||||
a = argv[0][0];
|
||||
++a;
|
||||
#pragma omp error
|
||||
#pragma omp error at(execution)
|
||||
{
|
||||
int b = 10;
|
||||
T c = 100;
|
||||
a = b + c;
|
||||
}
|
||||
#pragma omp error
|
||||
#pragma omp error at(execution)
|
||||
foo();
|
||||
return N;
|
||||
}
|
||||
@ -47,16 +47,16 @@ return N;
|
||||
// CHECK: int main(int argc, char **argv)
|
||||
// CHECK-NEXT: int b = argc, c, d, e, f, g;
|
||||
// CHECK-NEXT: static int a;
|
||||
// CHECK-NEXT: #pragma omp error
|
||||
// CHECK-NEXT: #pragma omp error at(execution)
|
||||
// CHECK-NEXT: a = 2;
|
||||
// CHECK-NEXT: #pragma omp error
|
||||
// CHECK-NEXT: #pragma omp error at(execution)
|
||||
// CHECK-NEXT: foo();
|
||||
int main (int argc, char **argv) {
|
||||
int b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
#pragma omp error
|
||||
#pragma omp error at(execution)
|
||||
a=2;
|
||||
#pragma omp error
|
||||
#pragma omp error at(execution)
|
||||
foo();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -7,19 +7,19 @@ T tmain(T argc) {
|
||||
if (argc)
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
if (argc) {
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
}
|
||||
while (argc)
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
while (argc) {
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
}
|
||||
do
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
while (argc)
|
||||
;
|
||||
do {
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
} while (argc);
|
||||
switch (argc)
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
@ -28,47 +28,75 @@ T tmain(T argc) {
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
switch (argc)
|
||||
case 1: {
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
}
|
||||
switch (argc) {
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
case 1:
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
break;
|
||||
default: {
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
} break;
|
||||
}
|
||||
for (;;)
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
for (;;) {
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
}
|
||||
label:
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
label1 : {
|
||||
#pragma omp error
|
||||
#pragma omp error // expected-error {{ERROR}}
|
||||
}
|
||||
if (1)
|
||||
label2:
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error at() // expected-error {{expected 'compilation' or 'execution' in OpenMP clause 'at'}}
|
||||
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error at(up) // expected-error {{expected 'compilation' or 'execution' in OpenMP clause 'at'}}
|
||||
|
||||
// expected-error@+3 {{ERROR}}
|
||||
// expected-error@+2 {{expected ')'}}
|
||||
// expected-note@+1 {{to match this '('}}
|
||||
#pragma omp error at(up(a)) // expected-error {{expected 'compilation' or 'execution' in OpenMP clause 'at'}}
|
||||
|
||||
#pragma omp error at(execution) // no error
|
||||
|
||||
#pragma omp error at(compilation) // expected-error {{ERROR}}
|
||||
return T();
|
||||
}
|
||||
|
||||
#pragma omp error at(execution) // expected-error {{unexpected 'execution' modifier in non-executable context}}
|
||||
|
||||
#pragma omp error at(compilation) // expected-error {{ERROR}}
|
||||
class A {
|
||||
|
||||
#pragma omp error at(compilation) // expected-error {{ERROR}}
|
||||
|
||||
#pragma omp error at(execution) // expected-error {{unexpected 'execution' modifier in non-executable context}}
|
||||
int A;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
;
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp error'}}
|
||||
#pragma omp error unknown // expected-warning {{extra tokens at the end of '#pragma omp error' are ignored}}
|
||||
if (argc)
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
if (argc) {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
}
|
||||
while (argc)
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
while (argc) {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
}
|
||||
do
|
||||
@ -76,6 +104,7 @@ int main(int argc, char **argv) {
|
||||
while (argc)
|
||||
;
|
||||
do {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
} while (argc);
|
||||
switch (argc)
|
||||
@ -85,25 +114,32 @@ int main(int argc, char **argv) {
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
switch (argc)
|
||||
case 1: {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
}
|
||||
switch (argc) {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
case 1:
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
break;
|
||||
default: {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
} break;
|
||||
}
|
||||
for (;;)
|
||||
#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
|
||||
for (;;) {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
}
|
||||
label:
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
label1 : {
|
||||
// expected-error@+1 {{ERROR}}
|
||||
#pragma omp error
|
||||
}
|
||||
if (1)
|
||||
|
||||
@ -2443,6 +2443,8 @@ void OMPClauseEnqueue::VisitOMPDynamicAllocatorsClause(
|
||||
void OMPClauseEnqueue::VisitOMPAtomicDefaultMemOrderClause(
|
||||
const OMPAtomicDefaultMemOrderClause *) {}
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPAtClause(const OMPAtClause *) {}
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPDeviceClause(const OMPDeviceClause *C) {
|
||||
Visitor->AddStmt(C->getDevice());
|
||||
}
|
||||
|
||||
@ -1868,6 +1868,7 @@ CHECK_SIMPLE_CLAUSE(Init, OMPC_init)
|
||||
CHECK_SIMPLE_CLAUSE(Use, OMPC_use)
|
||||
CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants)
|
||||
CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext)
|
||||
CHECK_SIMPLE_CLAUSE(At, OMPC_at)
|
||||
CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter)
|
||||
CHECK_SIMPLE_CLAUSE(When, OMPC_when)
|
||||
CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args)
|
||||
|
||||
@ -301,6 +301,9 @@ def OMPC_AtomicDefaultMemOrder : Clause<"atomic_default_mem_order"> {
|
||||
let clangClass = "OMPAtomicDefaultMemOrderClause";
|
||||
let flangClass = "OmpAtomicDefaultMemOrderClause";
|
||||
}
|
||||
def OMPC_At : Clause<"at"> {
|
||||
let clangClass = "OMPAtClause";
|
||||
}
|
||||
def OMPC_Allocate : Clause<"allocate"> {
|
||||
let clangClass = "OMPAllocateClause";
|
||||
let flangClass = "OmpAllocateClause";
|
||||
@ -527,7 +530,11 @@ def OMP_Critical : Directive<"critical"> {
|
||||
}
|
||||
def OMP_TaskYield : Directive<"taskyield"> {}
|
||||
def OMP_Barrier : Directive<"barrier"> {}
|
||||
def OMP_Error : Directive<"error"> {}
|
||||
def OMP_Error : Directive<"error"> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<OMPC_At>
|
||||
];
|
||||
}
|
||||
def OMP_TaskWait : Directive<"taskwait"> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<OMPC_Depend, 50>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user