From 095cecbe0ded16f2e66435d938fdc3cb1869713f Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Thu, 20 Feb 2020 19:50:47 -0600 Subject: [PATCH] [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 --- clang/include/clang/AST/OpenMPClause.h | 6 +- clang/include/clang/Basic/DiagnosticParseKinds.td | 4 +- clang/include/clang/Parse/Parser.h | 16 +++ clang/lib/AST/OpenMPClause.cpp | 7 +- clang/lib/Basic/OpenMPKinds.cpp | 4 + clang/lib/CodeGen/CGOpenMPRuntime.cpp | 13 +- clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 8 ++ clang/lib/Parse/ParseOpenMP.cpp | 156 ++++++++++++++++----- clang/lib/Sema/SemaOpenMP.cpp | 20 +++ .../AST/ast-dump-openmp-begin-declare-variant.c | 55 ++++++++ ...-declare-variant_no_end_for_matching_selector.c | 33 +++++ clang/test/OpenMP/begin_declare_variant_messages.c | 151 ++++++++++++++++++++ clang/test/OpenMP/declare_variant_messages.c | 5 +- clang/test/OpenMP/declare_variant_messages.cpp | 8 +- llvm/include/llvm/Frontend/OpenMP/OMPKinds.def | 2 + llvm/lib/Frontend/OpenMP/OMPContext.cpp | 2 + 16 files changed, 444 insertions(+), 46 deletions(-) create mode 100644 clang/test/AST/ast-dump-openmp-begin-declare-variant.c create mode 100644 clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c create mode 100644 clang/test/OpenMP/begin_declare_variant_messages.c diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 29c251e..4abe598 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -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; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index dcbb0d3..482b693 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -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< diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index d0e2540..6ebceee 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -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, diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index dc74a95..65ecd16 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -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. diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index e8bf41d..7a7c66c 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -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"); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 58c5334..6dc3f0d 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -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()) { 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()); } diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 4b5c855..dcf3ef1 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -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: diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index d47051c..1eca154 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -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) << ""; + } Score = ExprResult(); } @@ -1334,6 +1346,29 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, return; } + OMPTraitInfo TI; + if (parseOMPDeclareVariantMatchClause(Loc, TI)) + return; + + Optional> 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> 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 } + // + // { #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); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 31921ea..19b205c 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -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: diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant.c b/clang/test/AST/ast-dump-openmp-begin-declare-variant.c new file mode 100644 index 0000000..fb495b1 --- /dev/null +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant.c @@ -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 {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: -FunctionDecl {{.*}} line:{{.*}}:5 used also_after 'int (void)' +// CHECK-NEXT: -CompoundStmt {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 0 +// CHECK-NEXT: `-FunctionDecl {{.*}} line:{{.*}}:5 test 'int ()' +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: `-ReturnStmt {{.*}} +// CHECK-NEXT: `-BinaryOperator {{.*}} 'int' '+' +// CHECK-NEXT: |-CallExpr {{.*}} 'int' +// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'int (*)(void)' +// CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int (void)' Function {{.*}} 'also_after' 'int (void)' +// CHECK-NEXT: `-CallExpr {{.*}} 'int' +// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int (*)(void)' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'int (void)' Function {{.*}} 'also_before' 'int (void)' diff --git a/clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c b/clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c new file mode 100644 index 0000000..406776b --- /dev/null +++ b/clang/test/OpenMP/begin-declare-variant_no_end_for_matching_selector.c @@ -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'}} diff --git a/clang/test/OpenMP/begin_declare_variant_messages.c b/clang/test/OpenMP/begin_declare_variant_messages.c new file mode 100644 index 0000000..96faa3f --- /dev/null +++ b/clang/test/OpenMP/begin_declare_variant_messages.c @@ -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 (''); 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 (''); 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() :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()}) // 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(): 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 (''); 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'}} diff --git a/clang/test/OpenMP/declare_variant_messages.c b/clang/test/OpenMP/declare_variant_messages.c index 7b87e69..546fc1e 100644 --- a/clang/test/OpenMP/declare_variant_messages.c +++ b/clang/test/OpenMP/declare_variant_messages.c @@ -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 (''); 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 (''); 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: }} 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}} diff --git a/clang/test/OpenMP/declare_variant_messages.cpp b/clang/test/OpenMP/declare_variant_messages.cpp index f9950a8..78bacbe 100644 --- a/clang/test/OpenMP/declare_variant_messages.cpp +++ b/clang/test/OpenMP/declare_variant_messages.cpp @@ -43,8 +43,8 @@ T foofoo(); #pragma omp declare variant(foofoo ) 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 ) 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 ) 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 ) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} -#pragma omp declare variant(foofoo ) 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 ) 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 (''); score ignored}} +#pragma omp declare variant(foofoo ) 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 (''); 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 ) 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 ) match(device={kind(score(foofoo ()) 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()'); 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 ) 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 ) 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 ) 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 ) 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 ) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}} -#pragma omp declare variant(foofoo ) 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 ) 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 (''); score ignored}} +#pragma omp declare variant(foofoo ) 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 (''); 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 ) 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 ) match(device={kind(score(foofoo ()) 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()'); 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 ) 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}} diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index 5ed472b..c80ecc7 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -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) diff --git a/llvm/lib/Frontend/OpenMP/OMPContext.cpp b/llvm/lib/Frontend/OpenMP/OMPContext.cpp index 748caa6..505d4e9 100644 --- a/llvm/lib/Frontend/OpenMP/OMPContext.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPContext.cpp @@ -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 ""; S.pop_back(); return S; } -- 2.7.4