[OpenMP] `omp begin/end declare variant` - part 1, parsing

This is the first part extracted from D71179 and cleaned up.

This patch provides parsing support for `omp begin/end declare variant`,
as defined in OpenMP technical report 8 (TR8) [0].

A major purpose of this patch is to provide proper math.h/cmath support
for OpenMP target offloading. See PR42061, PR42798, PR42799. The current
code was developed with this feature in mind, see [1].

[0] https://www.openmp.org/wp-content/uploads/openmp-TR8.pdf
[1] https://reviews.llvm.org/D61399#change-496lQkg0mhRN

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D74941
This commit is contained in:
Johannes Doerfert 2020-02-20 19:50:47 -06:00
parent b29322435a
commit 095cecbe0d
16 changed files with 444 additions and 46 deletions

View File

@ -7178,9 +7178,11 @@ public:
/// former is a flat representation the actual main difference is that the
/// latter uses clang::Expr to store the score/condition while the former is
/// independent of clang. Thus, expressions and conditions are evaluated in
/// this method.
/// this method. If \p DeviceSetOnly is true, only the device selector set, if
/// present, is put in \p VMI, otherwise all selector sets are put in \p VMI.
void getAsVariantMatchInfo(ASTContext &ASTCtx,
llvm::omp::VariantMatchInfo &VMI) const;
llvm::omp::VariantMatchInfo &VMI,
bool DeviceSetOnly) const;
/// Print a human readable representation into \p OS.
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;

View File

@ -1232,8 +1232,8 @@ def err_omp_map_type_modifier_missing : Error<
"missing map type modifier">;
def err_omp_declare_simd_inbranch_notinbranch : Error<
"unexpected '%0' clause, '%1' is specified already">;
def err_expected_end_declare_target : Error<
"expected '#pragma omp end declare target'">;
def err_expected_end_declare_target_or_variant : Error<
"expected '#pragma omp end declare %select{target|variant}0'">;
def err_omp_declare_target_unexpected_clause: Error<
"unexpected '%0' clause, only %select{'to' or 'link'|'to', 'link' or 'device_type'}1 clauses expected">;
def err_omp_expected_clause: Error<

View File

@ -2963,9 +2963,14 @@ private:
/// Parses OpenMP context selectors.
bool parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI);
/// Parse a `match` clause for an '#pragma omp declare variant'. Return true
/// if there was an error.
bool parseOMPDeclareVariantMatchClause(SourceLocation Loc, OMPTraitInfo &TI);
/// Parse clauses for '#pragma omp declare variant'.
void ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr, CachedTokens &Toks,
SourceLocation Loc);
/// Parse clauses for '#pragma omp declare target'.
DeclGroupPtrTy ParseOMPDeclareTargetClauses();
/// Parse '#pragma omp end declare target'.
@ -2976,6 +2981,17 @@ private:
/// it is not the current token.
void skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind);
/// Check the \p FoundKind against the \p ExpectedKind, if not issue an error
/// that the "end" matching the "begin" directive of kind \p BeginKind was not
/// found. Finally, if the expected kind was found or if \p SkipUntilOpenMPEnd
/// is set, skip ahead using the helper `skipUntilPragmaOpenMPEnd`.
void parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
OpenMPDirectiveKind ExpectedKind,
OpenMPDirectiveKind FoundKind,
SourceLocation MatchingLoc,
SourceLocation FoundLoc,
bool SkipUntilOpenMPEnd);
/// Parses declarative OpenMP directives.
DeclGroupPtrTy ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,

View File

@ -1868,9 +1868,12 @@ void OMPClausePrinter::VisitOMPExclusiveClause(OMPExclusiveClause *Node) {
}
}
void OMPTraitInfo::getAsVariantMatchInfo(
ASTContext &ASTCtx, VariantMatchInfo &VMI) const {
void OMPTraitInfo::getAsVariantMatchInfo(ASTContext &ASTCtx,
VariantMatchInfo &VMI,
bool DeviceSetOnly) const {
for (const OMPTraitSet &Set : Sets) {
if (DeviceSetOnly && Set.Kind != TraitSet::device)
continue;
for (const OMPTraitSelector &Selector : Set.Selectors) {
// User conditions are special as we evaluate the condition here.

View File

@ -1025,6 +1025,8 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_unknown:
@ -1288,6 +1290,8 @@ void clang::getOpenMPCaptureRegions(
case OMPD_end_declare_target:
case OMPD_requires:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");

View File

@ -7008,6 +7008,8 @@ emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
case OMPD_target_update:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@ -7321,6 +7323,8 @@ emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
case OMPD_target_update:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@ -9107,6 +9111,8 @@ getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
case OMPD_target_update:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@ -9886,6 +9892,8 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
case OMPD_target_update:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@ -10525,6 +10533,8 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@ -11395,7 +11405,8 @@ static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
const OMPTraitInfo &TI = *A->getTraitInfos();
VMIs.push_back(VariantMatchInfo());
TI.getAsVariantMatchInfo(CGM.getContext(), VMIs.back());
TI.getAsVariantMatchInfo(CGM.getContext(), VMIs.back(),
/* DeviceSetOnly */ false);
VariantExprs.push_back(A->getVariantFuncRef());
}

View File

@ -803,6 +803,8 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx,
case OMPD_target_update:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@ -881,6 +883,8 @@ static bool supportsSPMDExecutionMode(ASTContext &Ctx,
case OMPD_target_update:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@ -1052,6 +1056,8 @@ static bool hasNestedLightweightDirective(ASTContext &Ctx,
case OMPD_target_update:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@ -1136,6 +1142,8 @@ static bool supportsLightweightRuntime(ASTContext &Ctx,
case OMPD_target_update:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:

View File

@ -48,6 +48,8 @@ enum OpenMPDirectiveKindEx {
OMPD_target_teams_distribute_parallel,
OMPD_mapper,
OMPD_variant,
OMPD_begin,
OMPD_begin_declare,
};
// Helper to unify the enum class OpenMPDirectiveKind with its extension
@ -101,6 +103,7 @@ static unsigned getOpenMPDirectiveKindEx(StringRef S) {
.Case("update", OMPD_update)
.Case("mapper", OMPD_mapper)
.Case("variant", OMPD_variant)
.Case("begin", OMPD_begin)
.Default(OMPD_unknown);
}
@ -109,18 +112,21 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
// E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
// TODO: add other combined directives in topological order.
static const OpenMPDirectiveKindExWrapper F[][3] = {
{OMPD_begin, OMPD_declare, OMPD_begin_declare},
{OMPD_end, OMPD_declare, OMPD_end_declare},
{OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
{OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
{OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
{OMPD_declare, OMPD_simd, OMPD_declare_simd},
{OMPD_declare, OMPD_target, OMPD_declare_target},
{OMPD_declare, OMPD_variant, OMPD_declare_variant},
{OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
{OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
{OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
{OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
{OMPD_distribute_parallel_for, OMPD_simd,
OMPD_distribute_parallel_for_simd},
{OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
{OMPD_end, OMPD_declare, OMPD_end_declare},
{OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
{OMPD_target, OMPD_data, OMPD_target_data},
{OMPD_target, OMPD_enter, OMPD_target_enter},
@ -1124,13 +1130,19 @@ void Parser::parseOMPContextSelector(
// Parse '('.
(void)BDT.consumeOpen();
SourceLocation ScoreLoc = Tok.getLocation();
ExprResult Score = parseContextScore(*this);
if (!AllowsTraitScore && Score.isUsable()) {
Diag(Score.get()->getBeginLoc(),
diag::warn_omp_ctx_incompatible_score_for_property)
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
<< getOpenMPContextTraitSetName(Set) << Score.get();
if (!AllowsTraitScore && !Score.isUnset()) {
if (Score.isUsable()) {
Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
<< getOpenMPContextTraitSetName(Set) << Score.get();
} else {
Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
<< getOpenMPContextTraitSelectorName(TISelector.Kind)
<< getOpenMPContextTraitSetName(Set) << "<invalid>";
}
Score = ExprResult();
}
@ -1334,6 +1346,29 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
return;
}
OMPTraitInfo TI;
if (parseOMPDeclareVariantMatchClause(Loc, TI))
return;
Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
Actions.checkOpenMPDeclareVariantFunction(
Ptr, AssociatedFunction.get(), TI,
SourceRange(Loc, Tok.getLocation()));
// Skip last tokens.
while (Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken();
if (DeclVarData && !TI.Sets.empty())
Actions.ActOnOpenMPDeclareVariantDirective(
DeclVarData->first, DeclVarData->second, TI,
SourceRange(Loc, Tok.getLocation()));
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
}
bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
OMPTraitInfo &TI) {
// Parse 'match'.
OpenMPClauseKind CKind = Tok.isAnnotation()
? OMPC_unknown
@ -1345,7 +1380,7 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
;
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
return;
return true;
}
(void)ConsumeToken();
// Parse '('.
@ -1356,31 +1391,15 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
;
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
return;
return true;
}
// Parse inner context selectors.
OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
parseOMPContextSelectors(Loc, TI);
// Parse ')'
(void)T.consumeClose();
Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
Actions.checkOpenMPDeclareVariantFunction(
Ptr, AssociatedFunction.get(), TI,
SourceRange(Loc, Tok.getLocation()));
// Skip last tokens.
while (Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken();
if (DeclVarData.hasValue() && !TI.Sets.empty())
Actions.ActOnOpenMPDeclareVariantDirective(
DeclVarData.getValue().first, DeclVarData.getValue().second, TI,
SourceRange(Loc, Tok.getLocation()));
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
return false;
}
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
@ -1530,17 +1549,36 @@ void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
ConsumeAnyToken();
}
void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
SourceLocation DTLoc) {
if (DKind != OMPD_end_declare_target) {
Diag(Tok, diag::err_expected_end_declare_target);
Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
OpenMPDirectiveKind ExpectedKind,
OpenMPDirectiveKind FoundKind,
SourceLocation BeginLoc,
SourceLocation FoundLoc,
bool SkipUntilOpenMPEnd) {
int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
if (FoundKind == ExpectedKind) {
ConsumeAnyToken();
skipUntilPragmaOpenMPEnd(ExpectedKind);
return;
}
ConsumeAnyToken();
skipUntilPragmaOpenMPEnd(OMPD_end_declare_target);
Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
<< DiagSelection;
Diag(BeginLoc, diag::note_matching)
<< ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
if (SkipUntilOpenMPEnd)
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
SourceLocation DKLoc) {
parseOMPEndDirective(OMPD_declare_target, OMPD_end_declare_target, DKind,
DKLoc, Tok.getLocation(),
/* SkipUntilOpenMPEnd */ false);
// Skip the last annot_pragma_openmp_end.
ConsumeAnyToken();
if (Tok.is(tok::annot_pragma_openmp_end))
ConsumeAnnotationToken();
}
/// Parsing of declarative OpenMP directives.
@ -1725,6 +1763,56 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
break;
}
case OMPD_begin_declare_variant: {
// The syntax is:
// { #pragma omp begin declare variant clause }
// <function-declaration-or-definition-sequence>
// { #pragma omp end declare variant }
//
ConsumeToken();
OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
if (parseOMPDeclareVariantMatchClause(Loc, TI))
break;
// Skip last tokens.
skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
VariantMatchInfo VMI;
ASTContext &ASTCtx = Actions.getASTContext();
TI.getAsVariantMatchInfo(ASTCtx, VMI, /* DeviceSetOnly */ true);
OMPContext OMPCtx(ASTCtx.getLangOpts().OpenMPIsDevice,
ASTCtx.getTargetInfo().getTriple());
if (isVariantApplicableInContext(VMI, OMPCtx))
break;
// Elide all the code till the matching end declare variant was found.
unsigned Nesting = 1;
SourceLocation DKLoc;
OpenMPDirectiveKind DK = OMPD_unknown;
do {
DKLoc = Tok.getLocation();
DK = parseOpenMPDirectiveKind(*this);
if (DK == OMPD_end_declare_variant)
--Nesting;
else if (DK == OMPD_begin_declare_variant)
++Nesting;
if (!Nesting || isEofOrEom())
break;
ConsumeAnyToken();
} while (true);
parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
if (isEofOrEom())
return nullptr;
break;
}
case OMPD_end_declare_variant:
// FIXME: With the sema changes we will keep track of nesting and be able to
// diagnose unmatchend OMPD_end_declare_variant.
ConsumeToken();
break;
case OMPD_declare_variant:
case OMPD_declare_simd: {
// The syntax is:
@ -2215,6 +2303,8 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_requires:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_variant:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);

View File

@ -3788,6 +3788,8 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
case OMPD_end_declare_target:
case OMPD_requires:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@ -5015,6 +5017,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPD_declare_simd:
case OMPD_requires:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@ -11222,6 +11226,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_teams:
@ -11294,6 +11300,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_teams:
@ -11371,6 +11379,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@ -11445,6 +11455,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@ -11520,6 +11532,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@ -11594,6 +11608,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@ -11667,6 +11683,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@ -11743,6 +11761,8 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_declare_variant:
case OMPD_begin_declare_variant:
case OMPD_end_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:

View File

@ -0,0 +1,55 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -ast-dump %s | FileCheck %s
#pragma omp begin declare variant match(device={kind(cpu)})
int also_before(void) {
return 0;
}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(gpu)})
int also_after(void) {
return 2;
}
int also_before(void) {
return 2;
}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(fpga)})
This text is never parsed!
#pragma omp end declare variant
int also_after(void) {
return 0;
}
int test() {
return also_after() + also_before();
}
// Make sure:
// - we do see the ast nodes for the cpu kind
// - we do not see the ast nodes for the gpu kind
// - we do not choke on the text in the kind(fpga) guarded scope.
// CHECK: -FunctionDecl {{.*}} <{{.*}}4:1, line:{{.*}}:1> line:{{.*}}:5 used also_before 'int (void)'
// CHECK-NEXT: -CompoundStmt {{.*}} <col:23, line:{{.*}}:1>
// CHECK-NEXT: `-ReturnStmt {{.*}} <line:{{.*}}:3, col:10>
// CHECK-NEXT: `-IntegerLiteral {{.*}} <col:10> 'int' 0
// CHECK-NEXT: -FunctionDecl {{.*}} <line:{{.*}}:1, line:{{.*}}:1> line:{{.*}}:5 used also_after 'int (void)'
// CHECK-NEXT: -CompoundStmt {{.*}} <col:22, line:{{.*}}:1>
// CHECK-NEXT: `-ReturnStmt {{.*}} <line:{{.*}}:3, col:10>
// CHECK-NEXT: `-IntegerLiteral {{.*}} <col:10> 'int' 0
// CHECK-NEXT: `-FunctionDecl {{.*}} <line:{{.*}}:1, line:{{.*}}:1> line:{{.*}}:5 test 'int ()'
// CHECK-NEXT: `-CompoundStmt {{.*}} <col:12, line:{{.*}}:1>
// CHECK-NEXT: `-ReturnStmt {{.*}} <line:{{.*}}:3, col:37>
// CHECK-NEXT: `-BinaryOperator {{.*}} <col:10, col:37> 'int' '+'
// CHECK-NEXT: |-CallExpr {{.*}} <col:10, col:21> 'int'
// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} <col:10> 'int (*)(void)' <FunctionToPointerDecay>
// CHECK-NEXT: | `-DeclRefExpr {{.*}} <col:10> 'int (void)' Function {{.*}} 'also_after' 'int (void)'
// CHECK-NEXT: `-CallExpr {{.*}} <col:25, col:37> 'int'
// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:25> 'int (*)(void)' <FunctionToPointerDecay>
// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:25> 'int (void)' Function {{.*}} 'also_before' 'int (void)'

View File

@ -0,0 +1,33 @@
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
#pragma omp begin declare variant match(device={kind(cpu)})
int also_before(void) {
return 0;
}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(gpu)}) // expected-note {{to match this '#pragma omp begin declare variant'}}
// The matching end is missing. Since the device clause is not matching we will
// cause us to elide the rest of the file and emit and error.
int also_after(void) {
return 2;
}
int also_before(void) {
return 2;
}
#pragma omp begin declare variant match(device={kind(fpga)})
This text is never parsed!
#pragma omp end declare variant
int also_after(void) {
return 0;
}
int test() {
return also_after() + also_before();
} // expected-error {{expected '#pragma omp end declare variant'}}

View File

@ -0,0 +1,151 @@
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
#pragma omp begin // expected-error {{expected an OpenMP directive}}
#pragma omp end declare variant
#pragma omp begin declare // expected-error {{expected an OpenMP directive}}
#pragma omp end declare variant
#pragma omp begin variant // expected-error {{expected an OpenMP directive}}
#pragma omp end declare variant
#pragma omp variant begin // expected-error {{expected an OpenMP directive}}
#pragma omp declare variant end // expected-error {{function declaration is expected after 'declare variant' directive}}
#pragma omp begin declare variant // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp end declare variant
// TODO: Issue an error message
#pragma omp end declare variant
#pragma omp end declare variant
#pragma omp end declare variant
#pragma omp end declare variant
int foo(void);
const int var;
#pragma omp begin declare variant // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp end declare variant
#pragma omp begin declare variant xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp end declare variant
#pragma omp begin declare variant match // expected-error {{expected '(' after 'match'}}
#pragma omp end declare variant
#pragma omp begin declare variant match( // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context set; set skipped}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match() // expected-warning {{expected identifier or string literal describing a context set; set skipped}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx=) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx=yyy) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx=yyy}) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-warning {{extra tokens at the end of '#pragma omp begin declare variant' are ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx={) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx={vvv, vvv}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx={vvv} xxx) // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(xxx={vvv}) xxx // expected-warning {{'xxx' is not a valid context set in a `declare variant`; set ignored}} expected-warning {{extra tokens at the end of '#pragma omp begin declare variant' are ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'implementation'; selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor}) // expected-warning {{the context selector 'vendor' in context set 'implementation' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor()}) // expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor(score(foo()) ibm)}) // expected-warning {{expected '':'' after the score expression; '':'' assumed}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor(score(5): ibm), vendor(llvm)}) // expected-warning {{the context selector 'vendor' was used already in the same 'omp declare variant' directive; selector ignored}} expected-note {{the previous context selector 'vendor' used here}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{the context selector 'kind' is not valid for the context set 'implementation'; selector ignored}} expected-note {{the context selector 'kind' can be nested in the context set 'device'; try 'match(device={kind(property)})'}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'device'; selector ignored}} expected-note {{context selector options are: 'kind' 'isa' 'arch'}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind}) // expected-warning {{the context selector 'kind' in context set 'device' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind()}) // expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(score(2 gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('2'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(score(foo()) ibm)}) // expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo()'); score ignored}} expected-warning {{'ibm' is not a valid context property for the context selector 'kind' and the context set 'device'; property ignored}} expected-note {{try 'match(implementation={vendor(ibm)})'}} expected-note {{the ignored property spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(score(5): host), kind(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'); score ignored}} expected-warning {{the context selector 'kind' was used already in the same 'omp declare variant' directive; selector ignored}} expected-note {{the previous context selector 'kind' used here}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device={kind(score(5): nohost), vendor(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'); score ignored}} expected-warning {{the context selector 'vendor' is not valid for the context set 'device'; selector ignored}} expected-note {{the context selector 'vendor' can be nested in the context set 'implementation'; try 'match(implementation={vendor(property)})'}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(foo()): cpu}) // expected-error {{expected ')'}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo()'); score ignored}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(foo()): cpu)) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo()'); score ignored}} expected-warning {{expected '}' after the context selectors for the context set "device"; '}' assumed}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(foo()): cpu)} // expected-error {{expected ')'}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo()'); score ignored}} expected-note {{to match this '('}}
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation = {vendor(score(foo) :llvm)})
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation = {vendor(score(foo()) :llvm)})
#pragma omp end declare variant
#pragma omp begin declare variant match(implementation = {vendor(score(<expr>) :llvm)}) // expected-error {{expected expression}} expected-error {{use of undeclared identifier 'expr'}} expected-error {{expected expression}}
#pragma omp end declare variant
#pragma omp begin declare variant match(user = {condition(foo)})
#pragma omp end declare variant
#pragma omp begin declare variant match(user = {condition(foo())})
#pragma omp end declare variant
#pragma omp begin declare variant match(user = {condition(<expr>)}) // expected-error {{expected expression}} expected-error {{use of undeclared identifier 'expr'}} expected-error {{expected expression}} expected-note {{the ignored selector spans until here}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(&var): cpu)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('&var'); score ignored}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(var): cpu)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('var'); score ignored}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(foo): cpu)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo'); score ignored}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(foo()): cpu)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo()'); score ignored}}
#pragma omp end declare variant
#pragma omp begin declare variant match(device = {kind(score(<expr>): cpu)}) // expected-error {{expected expression}} expected-error {{use of undeclared identifier 'expr'}} expected-error {{expected expression}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}}
#pragma omp end declare variant
// TODO: Issue an error message
#pragma omp begin declare variant match(device={kind(cpu)})
// The matching end is missing. Since the device clause is matching we will
// emit and error.
int also_before(void) {
return 0;
}
#pragma omp begin declare variant match(device={kind(gpu)}) // expected-note {{to match this '#pragma omp begin declare variant'}}
// The matching end is missing. Since the device clause is not matching we will
// cause us to elide the rest of the file and emit and error.
int also_after(void) {
return 2;
}
int also_before(void) {
return 2;
}
#pragma omp begin declare variant match(device={kind(fpga)})
This text is never parsed!
#pragma omp end declare variant
This text is also not parsed! // expected-error {{expected '#pragma omp end declare variant'}}

View File

@ -40,12 +40,13 @@ int foo(void);
#pragma omp declare variant(foo) match(device={kind}) // expected-warning {{the context selector 'kind' in context set 'device' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foo) match(device={kind(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(device={kind()}) // expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}}
#pragma omp declare variant(foo) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}}
#pragma omp declare variant(foo) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}}
#pragma omp declare variant(foo) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(device={kind(score(2 gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('2'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foo) match(device={kind(score(foo()) ibm)}) // expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo()'); score ignored}} expected-warning {{'ibm' is not a valid context property for the context selector 'kind' and the context set 'device'; property ignored}} expected-note {{try 'match(implementation={vendor(ibm)})'}} expected-note {{the ignored property spans until here}}
#pragma omp declare variant(foo) match(device={kind(score(5): host), kind(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'); score ignored}} expected-warning {{the context selector 'kind' was used already in the same 'omp declare variant' directive; selector ignored}} expected-note {{the previous context selector 'kind' used here}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foo) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'); score ignored}} expected-warning {{the context selector 'vendor' is not valid for the context set 'device'; selector ignored}} expected-note {{the context selector 'vendor' can be nested in the context set 'implementation'; try 'match(implementation={vendor(property)})'}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foo) match(implementation={extension("aaa")}) // expected-warning {{'aaa' is not a valid context property for the context selector 'extension' and the context set 'implementation'; property ignored}} expected-note {{context property options are: <none>}} expected-note {{the ignored property spans until here}}
int bar(void);
#pragma omp declare variant(foo) match(implementation = {vendor(score(foo) :llvm)}) // expected-warning {{score expressions in the OpenMP context selector need to be constant; foo is not and will be ignored}}

View File

@ -43,8 +43,8 @@ T foofoo();
#pragma omp declare variant(foofoo <int>) match(device={kind}) // expected-warning {{the context selector 'kind' in context set 'device' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <int>) match(device={kind(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(device={kind()}) // expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score(2 gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('2'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score(foofoo <int>()) ibm)}) // expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foofoo<int>()'); score ignored}} expected-warning {{'ibm' is not a valid context property for the context selector 'kind' and the context set 'device'; property ignored}} expected-note {{try 'match(implementation={vendor(ibm)})'}} expected-note {{the ignored property spans until here}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score(5): host), kind(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'); score ignored}} expected-warning {{the context selector 'kind' was used already in the same 'omp declare variant' directive; selector ignored}} expected-note {{the previous context selector 'kind' used here}} expected-note {{the ignored selector spans until here}}
@ -83,8 +83,8 @@ int bar();
#pragma omp declare variant(foofoo <int>) match(device={kind}) // expected-warning {{the context selector 'kind' in context set 'device' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <int>) match(device={kind(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(device={kind()}) // expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('<invalid>'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score(C gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('C'); score ignored}} expected-warning {{expected identifier or string literal describing a context property; property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score(foofoo <int>()) ibm)}) // expected-warning {{expected '':'' after the score expression; '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foofoo<int>()'); score ignored}} expected-warning {{'ibm' is not a valid context property for the context selector 'kind' and the context set 'device'; property ignored}} expected-note {{try 'match(implementation={vendor(ibm)})'}} expected-note {{the ignored property spans until here}}
#pragma omp declare variant(foofoo <int>) match(device={kind(score(C+5): host), kind(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('C + 5'); score ignored}} expected-warning {{the context selector 'kind' was used already in the same 'omp declare variant' directive; selector ignored}} expected-note {{the previous context selector 'kind' used here}} expected-note {{the ignored selector spans until here}}

View File

@ -93,6 +93,8 @@ __OMP_DIRECTIVE_EXT(parallel_master_taskloop_simd,
"parallel master taskloop simd")
__OMP_DIRECTIVE(depobj)
__OMP_DIRECTIVE(scan)
__OMP_DIRECTIVE_EXT(begin_declare_variant, "begin declare variant")
__OMP_DIRECTIVE_EXT(end_declare_variant, "end declare variant")
// Has to be the last because Clang implicitly expects it to be.
__OMP_DIRECTIVE(unknown)

View File

@ -450,6 +450,8 @@ llvm::omp::listOpenMPContextTraitProperties(TraitSet Set,
StringRef(Str) != "invalid") \
S.append("'").append(Str).append("'").append(" ");
#include "llvm/Frontend/OpenMP/OMPKinds.def"
if (S.empty())
return "<none>";
S.pop_back();
return S;
}