r371892 - [OPENMP5.0]Add basic support for declare variant directive.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 13 13:18:17 PDT 2019
Author: abataev
Date: Fri Sep 13 13:18:17 2019
New Revision: 371892
URL: http://llvm.org/viewvc/llvm-project?rev=371892&view=rev
Log:
[OPENMP5.0]Add basic support for declare variant directive.
Added basic support for declare variant directive and its match clause
with user context selector.
Added:
cfe/trunk/test/OpenMP/declare_variant_messages.c
cfe/trunk/test/OpenMP/declare_variant_messages.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Basic/OpenMPKinds.def
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Basic/OpenMPKinds.cpp
cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
cfe/trunk/lib/Parse/ParseOpenMP.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaOpenMP.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Sep 13 13:18:17 2019
@@ -201,6 +201,7 @@ def err_invalid_token_after_declarator_s
"invalid %0 at end of declaration; did you mean '='?">;
def err_expected_statement : Error<"expected statement">;
def err_expected_lparen_after : Error<"expected '(' after '%0'">;
+def err_expected_lbrace_after : Error<"expected '{' after '%0'">;
def err_expected_rparen_after : Error<"expected ')' after '%0'">;
def err_expected_punc : Error<"expected ')' or ',' after '%0'">;
def err_expected_less_after : Error<"expected '<' after '%0'">;
@@ -1177,8 +1178,8 @@ def err_omp_expected_identifier_for_crit
"expected identifier specifying the name of the 'omp critical' directive">;
def err_omp_expected_reduction_identifier : Error<
"expected identifier or one of the following operators: '+', '-', '*', '&', '|', '^', '&&', or '||'">;
-def err_omp_decl_in_declare_simd : Error<
- "function declaration is expected after 'declare simd' directive">;
+def err_omp_decl_in_declare_simd_variant : Error<
+ "function declaration is expected after 'declare %select{simd|variant}0' directive">;
def err_omp_unknown_map_type : Error<
"incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
def err_omp_unknown_map_type_modifier : Error<
@@ -1199,6 +1200,12 @@ def err_omp_mapper_illegal_identifier :
"illegal OpenMP user-defined mapper identifier">;
def err_omp_mapper_expected_declarator : Error<
"expected declarator on 'omp declare mapper' directive">;
+def err_omp_declare_variant_wrong_clause : Error<
+ "expected '%0' clause on 'omp declare variant' directive">;
+def err_omp_declare_variant_no_ctx_selector : Error<
+ "expected context selector in '%0' clause on 'omp declare variant' directive">;
+def err_omp_declare_variant_equal_expected : Error<
+ "expected '=' after '%0' context selector set name on 'omp declare variant' directive">;
def warn_omp_more_one_device_type_clause : Warning<
"more than one 'device_type' clause is specified">,
InGroup<OpenMPClauses>;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep 13 13:18:17 2019
@@ -9213,10 +9213,10 @@ def err_omp_single_copyprivate_with_nowa
"the 'copyprivate' clause must not be used with the 'nowait' clause">;
def note_omp_nowait_clause_here : Note<
"'nowait' clause is here">;
-def err_omp_single_decl_in_declare_simd : Error<
- "single declaration is expected after 'declare simd' directive">;
+def err_omp_single_decl_in_declare_simd_variant : Error<
+ "single declaration is expected after 'declare %select{simd|variant}0' directive">;
def err_omp_function_expected : Error<
- "'#pragma omp declare simd' can only be applied to functions">;
+ "'#pragma omp declare %select{simd|variant}0' can only be applied to functions">;
def err_omp_wrong_cancel_region : Error<
"one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">;
def err_omp_parent_cancel_region_nowait : Error<
@@ -9408,6 +9408,27 @@ def note_omp_marked_device_type_here : N
def warn_omp_declare_target_after_first_use : Warning<
"declaration marked as declare target after first use, it may lead to incorrect results">,
InGroup<OpenMPTarget>;
+def err_omp_declare_variant_incompat_attributes : Error<
+ "'#pragma omp declare variant' is not compatible with any target-specific attributes">;
+def err_omp_declare_variant_after_used : Error<
+ "'#pragma omp declare variant' cannot be applied for function after first "
+ "usage">;
+def err_omp_declare_variant_noproto : Error<
+ "function with '#pragma omp declare variant' must have a prototype">;
+def note_omp_declare_variant_specified_here : Note<
+ "'#pragma omp declare variant' for function specified here">;
+def err_omp_declare_variant_doesnt_support : Error<
+ "'#pragma omp declare variant' does not "
+ "support %select{function templates|virtual functions|"
+ "deduced return types|constructors|destructors|deleted functions|"
+ "defaulted functions|constexpr functions|consteval function}0">;
+def err_omp_declare_variant_diff : Error<
+ "function with '#pragma omp declare variant' has a different %select{calling convention"
+ "|return type|constexpr specification|inline specification|storage class|"
+ "linkage}0">;
+def err_omp_declare_variant_incompat_types : Error<
+ "variant in '#pragma omp declare variant' with type %0 is incompatible with type %1"
+ >;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Fri Sep 13 13:18:17 2019
@@ -251,6 +251,7 @@ OPENMP_DIRECTIVE_EXT(target_teams_distri
OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for_simd, "target teams distribute parallel for simd")
OPENMP_DIRECTIVE_EXT(target_teams_distribute_simd, "target teams distribute simd")
OPENMP_DIRECTIVE(allocate)
+OPENMP_DIRECTIVE_EXT(declare_variant, "declare variant")
// OpenMP clauses.
OPENMP_CLAUSE(allocator, OMPAllocatorClause)
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Sep 13 13:18:17 2019
@@ -2834,6 +2834,10 @@ private:
DeclGroupPtrTy ParseOMPDeclareSimdClauses(DeclGroupPtrTy Ptr,
CachedTokens &Toks,
SourceLocation Loc);
+ /// Parse clauses for '#pragma omp declare variant'.
+ DeclGroupPtrTy ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr,
+ CachedTokens &Toks,
+ SourceLocation Loc);
/// Parse clauses for '#pragma omp declare target'.
DeclGroupPtrTy ParseOMPDeclareTargetClauses();
/// Parse '#pragma omp end declare target'.
@@ -2927,7 +2931,8 @@ public:
/// Parses simple expression in parens for single-expression clauses of OpenMP
/// constructs.
/// \param RLoc Returned location of right paren.
- ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc);
+ ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc,
+ bool IsAddressOfOperand = false);
/// Data used for parsing list of variables in OpenMP clauses.
struct OpenMPVarListDataTy {
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Sep 13 13:18:17 2019
@@ -9090,6 +9090,15 @@ private:
SourceRange SrcRange = SourceRange());
public:
+ /// Checks if the variant/multiversion functions are compatible.
+ bool areMultiversionVariantFunctionsCompatible(
+ const FunctionDecl *OldFD, const FunctionDecl *NewFD,
+ const PartialDiagnostic &NoProtoDiagID,
+ const PartialDiagnosticAt &NoteCausedDiagIDAt,
+ const PartialDiagnosticAt &NoSupportDiagIDAt,
+ const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported,
+ bool ConstexprSupported);
+
/// Function tries to capture lambda's captured variables in the OpenMP region
/// before the original lambda is captured.
void tryCaptureOpenMPLambdas(ValueDecl *V);
@@ -9514,6 +9523,16 @@ public:
ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR);
+ /// Called on well-formed '\#pragma omp declare variant' after parsing of
+ /// the associated method/function.
+ /// \param DG Function declaration to which declare variant directive is
+ /// applied to.
+ /// \param VariantRef Expression that references the variant function, which
+ /// must be used instead of the original one, specified in \p DG.
+ DeclGroupPtrTy ActOnOpenMPDeclareVariantDirective(DeclGroupPtrTy DG,
+ Expr *VariantRef,
+ SourceRange SR);
+
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
SourceLocation StartLoc,
Modified: cfe/trunk/lib/Basic/OpenMPKinds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/OpenMPKinds.cpp?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/OpenMPKinds.cpp (original)
+++ cfe/trunk/lib/Basic/OpenMPKinds.cpp Fri Sep 13 13:18:17 2019
@@ -606,8 +606,6 @@ bool clang::isAllowedClauseForDirective(
break;
}
break;
- case OMPD_declare_simd:
- break;
case OMPD_cancel:
switch (CKind) {
#define OPENMP_CANCEL_CLAUSE(Name) \
@@ -849,6 +847,8 @@ bool clang::isAllowedClauseForDirective(
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_declare_reduction:
+ case OMPD_declare_simd:
+ case OMPD_declare_variant:
break;
}
return false;
@@ -1078,6 +1078,7 @@ void clang::getOpenMPCaptureRegions(
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_requires:
+ case OMPD_declare_variant:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Fri Sep 13 13:18:17 2019
@@ -6770,6 +6770,7 @@ emitNumTeamsForTargetDirective(CodeGenFu
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_target_update:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@@ -7075,6 +7076,7 @@ emitNumThreadsForTargetDirective(CodeGen
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_target_update:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@@ -8826,6 +8828,7 @@ getNestedDistributeDirective(ASTContext
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_target_update:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@@ -9583,6 +9586,7 @@ void CGOpenMPRuntime::scanForTargetRegio
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_target_update:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@@ -10205,6 +10209,7 @@ void CGOpenMPRuntime::emitTargetDataStan
case OMPD_teams_distribute_parallel_for:
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp Fri Sep 13 13:18:17 2019
@@ -795,6 +795,7 @@ static bool hasNestedSPMDDirective(ASTCo
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_target_update:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@@ -865,6 +866,7 @@ static bool supportsSPMDExecutionMode(AS
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_target_update:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@@ -1028,6 +1030,7 @@ static bool hasNestedLightweightDirectiv
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_target_update:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
@@ -1104,6 +1107,7 @@ static bool supportsLightweightRuntime(A
case OMPD_teams_distribute_parallel_for_simd:
case OMPD_target_update:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_declare_reduction:
Modified: cfe/trunk/lib/Parse/ParseOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseOpenMP.cpp?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseOpenMP.cpp (original)
+++ cfe/trunk/lib/Parse/ParseOpenMP.cpp Fri Sep 13 13:18:17 2019
@@ -42,6 +42,7 @@ enum OpenMPDirectiveKindEx {
OMPD_teams_distribute_parallel,
OMPD_target_teams_distribute_parallel,
OMPD_mapper,
+ OMPD_variant,
};
class DeclDirectiveListParserHelper final {
@@ -80,6 +81,7 @@ static unsigned getOpenMPDirectiveKindEx
.Case("reduction", OMPD_reduction)
.Case("update", OMPD_update)
.Case("mapper", OMPD_mapper)
+ .Case("variant", OMPD_variant)
.Default(OMPD_unknown);
}
@@ -93,6 +95,7 @@ static OpenMPDirectiveKind parseOpenMPDi
{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_distribute, OMPD_parallel, OMPD_distribute_parallel},
{OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
{OMPD_distribute_parallel_for, OMPD_simd,
@@ -752,6 +755,7 @@ Parser::ParseOMPDeclareSimdClauses(Parse
/*IsReinject*/ true);
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
FNContextRAII FnContext(*this, Ptr);
OMPDeclareSimdDeclAttr::BranchStateTy BS =
@@ -782,6 +786,107 @@ Parser::ParseOMPDeclareSimdClauses(Parse
LinModifiers, Steps, SourceRange(Loc, EndLoc));
}
+/// Parses clauses for 'declare variant' directive.
+/// clause:
+/// 'match' '('
+/// <selector_set_name> '=' '{' <context_selectors> '}'
+/// ')'
+static bool parseDeclareVariantClause(Parser &P) {
+ Token Tok = P.getCurToken();
+ // Parse 'match'.
+ if (!Tok.is(tok::identifier) ||
+ P.getPreprocessor().getSpelling(Tok).compare("match")) {
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
+ << "match";
+ while (!P.SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ return true;
+ }
+ (void)P.ConsumeToken();
+ // Parse '('.
+ BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after, "match"))
+ return true;
+ // Parse inner context selector.
+ Tok = P.getCurToken();
+ if (!Tok.is(tok::identifier)) {
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
+ << "match";
+ return true;
+ }
+ SmallString<16> Buffer;
+ StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
+ // Parse '='.
+ (void)P.ConsumeToken();
+ Tok = P.getCurToken();
+ if (Tok.isNot(tok::equal)) {
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
+ << CtxSelectorName;
+ return true;
+ }
+ (void)P.ConsumeToken();
+ // Unknown selector - just ignore it completely.
+ {
+ // Parse '{'.
+ BalancedDelimiterTracker TBr(P, tok::l_brace, tok::annot_pragma_openmp_end);
+ if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
+ return true;
+ while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ // Parse '}'.
+ (void)TBr.consumeClose();
+ }
+ // Parse ')'.
+ (void)T.consumeClose();
+ // TBD: add parsing of known context selectors.
+ return false;
+}
+
+/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
+Parser::DeclGroupPtrTy
+Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
+ CachedTokens &Toks, SourceLocation Loc) {
+ PP.EnterToken(Tok, /*IsReinject*/ true);
+ PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
+ /*IsReinject*/ true);
+ // Consume the previously pushed token.
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+
+ FNContextRAII FnContext(*this, Ptr);
+ // Parse function declaration id.
+ SourceLocation RLoc;
+ // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
+ // instead of MemberExprs.
+ ExprResult AssociatedFunction =
+ ParseOpenMPParensExpr(getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
+ /*IsAddressOfOperand=*/true);
+ if (!AssociatedFunction.isUsable()) {
+ if (!Tok.is(tok::annot_pragma_openmp_end))
+ while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+ return Ptr;
+ }
+
+ bool IsError = parseDeclareVariantClause(*this);
+ // Need to check for extra tokens.
+ if (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
+ << getOpenMPDirectiveName(OMPD_declare_variant);
+ while (Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ }
+ // Skip the last annot_pragma_openmp_end.
+ SourceLocation EndLoc = ConsumeAnnotationToken();
+ if (IsError)
+ return Ptr;
+ return Actions.ActOnOpenMPDeclareVariantDirective(
+ Ptr, AssociatedFunction.get(), SourceRange(Loc, EndLoc));
+}
+
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
///
/// default-clause:
@@ -1103,13 +1208,15 @@ Parser::DeclGroupPtrTy Parser::ParseOpen
}
break;
}
+ case OMPD_declare_variant:
case OMPD_declare_simd: {
// The syntax is:
- // { #pragma omp declare simd }
+ // { #pragma omp declare {simd|variant} }
// <function-declaration-or-definition>
//
- ConsumeToken();
CachedTokens Toks;
+ Toks.push_back(Tok);
+ ConsumeToken();
while(Tok.isNot(tok::annot_pragma_openmp_end)) {
Toks.push_back(Tok);
ConsumeAnyToken();
@@ -1133,10 +1240,15 @@ Parser::DeclGroupPtrTy Parser::ParseOpen
}
}
if (!Ptr) {
- Diag(Loc, diag::err_omp_decl_in_declare_simd);
+ Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
+ << (DKind == OMPD_declare_simd ? 0 : 1);
return DeclGroupPtrTy();
}
- return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
+ if (DKind == OMPD_declare_simd)
+ return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
+ assert(DKind == OMPD_declare_variant &&
+ "Expected declare variant directive only");
+ return ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
}
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
@@ -1572,6 +1684,7 @@ Parser::ParseOpenMPDeclarativeOrExecutab
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_requires:
+ case OMPD_declare_variant:
Diag(Tok, diag::err_omp_unexpected_directive)
<< 1 << getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end);
@@ -1831,14 +1944,15 @@ OMPClause *Parser::ParseOpenMPClause(Ope
/// constructs.
/// \param RLoc Returned location of right paren.
ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
- SourceLocation &RLoc) {
+ SourceLocation &RLoc,
+ bool IsAddressOfOperand) {
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
return ExprError();
SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(
- /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
+ /*isUnaryExpression=*/false, IsAddressOfOperand, NotTypeCast));
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Sep 13 13:18:17 2019
@@ -9670,10 +9670,13 @@ static bool HasNonMultiVersionAttributes
return false;
}
-static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
- const FunctionDecl *NewFD,
- bool CausesMV,
- MultiVersionKind MVType) {
+bool Sema::areMultiversionVariantFunctionsCompatible(
+ const FunctionDecl *OldFD, const FunctionDecl *NewFD,
+ const PartialDiagnostic &NoProtoDiagID,
+ const PartialDiagnosticAt &NoteCausedDiagIDAt,
+ const PartialDiagnosticAt &NoSupportDiagIDAt,
+ const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported,
+ bool ConstexprSupported) {
enum DoesntSupport {
FuncTemplates = 0,
VirtFuncs = 1,
@@ -9691,123 +9694,85 @@ static bool CheckMultiVersionAdditionalR
ConstexprSpec = 2,
InlineSpec = 3,
StorageClass = 4,
- Linkage = 5
+ Linkage = 5,
};
- bool IsCPUSpecificCPUDispatchMVType =
- MVType == MultiVersionKind::CPUDispatch ||
- MVType == MultiVersionKind::CPUSpecific;
-
if (OldFD && !OldFD->getType()->getAs<FunctionProtoType>()) {
- S.Diag(OldFD->getLocation(), diag::err_multiversion_noproto);
- S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ Diag(OldFD->getLocation(), NoProtoDiagID);
+ Diag(NoteCausedDiagIDAt.first, NoteCausedDiagIDAt.second);
return true;
}
if (!NewFD->getType()->getAs<FunctionProtoType>())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_noproto);
-
- if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
- S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
- if (OldFD)
- S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
- return true;
- }
-
- // For now, disallow all other attributes. These should be opt-in, but
- // an analysis of all of them is a future FIXME.
- if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) {
- S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
- << IsCPUSpecificCPUDispatchMVType;
- S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
- return true;
- }
+ return Diag(NewFD->getLocation(), NoProtoDiagID);
- if (HasNonMultiVersionAttributes(NewFD, MVType))
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
- << IsCPUSpecificCPUDispatchMVType;
-
- if (NewFD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << FuncTemplates;
+ if (!TemplatesSupported &&
+ NewFD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << FuncTemplates;
if (const auto *NewCXXFD = dyn_cast<CXXMethodDecl>(NewFD)) {
if (NewCXXFD->isVirtual())
- return S.Diag(NewCXXFD->getLocation(),
- diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << VirtFuncs;
-
- if (const auto *NewCXXCtor = dyn_cast<CXXConstructorDecl>(NewFD))
- return S.Diag(NewCXXCtor->getLocation(),
- diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << Constructors;
-
- if (const auto *NewCXXDtor = dyn_cast<CXXDestructorDecl>(NewFD))
- return S.Diag(NewCXXDtor->getLocation(),
- diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << Destructors;
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << VirtFuncs;
+
+ if (isa<CXXConstructorDecl>(NewCXXFD))
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << Constructors;
+
+ if (isa<CXXDestructorDecl>(NewCXXFD))
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << Destructors;
}
if (NewFD->isDeleted())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << DeletedFuncs;
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << DeletedFuncs;
if (NewFD->isDefaulted())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << DefaultedFuncs;
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << DefaultedFuncs;
- if (NewFD->isConstexpr() && (MVType == MultiVersionKind::CPUDispatch ||
- MVType == MultiVersionKind::CPUSpecific))
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType
+ if (!ConstexprSupported && NewFD->isConstexpr())
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
<< (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
- QualType NewQType = S.getASTContext().getCanonicalType(NewFD->getType());
+ QualType NewQType = Context.getCanonicalType(NewFD->getType());
const auto *NewType = cast<FunctionType>(NewQType);
QualType NewReturnType = NewType->getReturnType();
if (NewReturnType->isUndeducedType())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support)
- << IsCPUSpecificCPUDispatchMVType << DeducedReturn;
-
- // Only allow transition to MultiVersion if it hasn't been used.
- if (OldFD && CausesMV && OldFD->isUsed(false))
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_after_used);
+ return Diag(NoSupportDiagIDAt.first, NoSupportDiagIDAt.second)
+ << DeducedReturn;
// Ensure the return type is identical.
if (OldFD) {
- QualType OldQType = S.getASTContext().getCanonicalType(OldFD->getType());
+ QualType OldQType = Context.getCanonicalType(OldFD->getType());
const auto *OldType = cast<FunctionType>(OldQType);
FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
if (OldTypeInfo.getCC() != NewTypeInfo.getCC())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << CallingConv;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << CallingConv;
QualType OldReturnType = OldType->getReturnType();
if (OldReturnType != NewReturnType)
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << ReturnType;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << ReturnType;
if (OldFD->getConstexprKind() != NewFD->getConstexprKind())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << ConstexprSpec;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << ConstexprSpec;
if (OldFD->isInlineSpecified() != NewFD->isInlineSpecified())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << InlineSpec;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << InlineSpec;
if (OldFD->getStorageClass() != NewFD->getStorageClass())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << StorageClass;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << StorageClass;
if (OldFD->isExternC() != NewFD->isExternC())
- return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff)
- << Linkage;
+ return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << Linkage;
- if (S.CheckEquivalentExceptionSpec(
+ if (CheckEquivalentExceptionSpec(
OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(),
NewFD->getType()->getAs<FunctionProtoType>(), NewFD->getLocation()))
return true;
@@ -9815,6 +9780,51 @@ static bool CheckMultiVersionAdditionalR
return false;
}
+static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD,
+ const FunctionDecl *NewFD,
+ bool CausesMV,
+ MultiVersionKind MVType) {
+ if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
+ S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
+ if (OldFD)
+ S.Diag(OldFD->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
+ bool IsCPUSpecificCPUDispatchMVType =
+ MVType == MultiVersionKind::CPUDispatch ||
+ MVType == MultiVersionKind::CPUSpecific;
+
+ // For now, disallow all other attributes. These should be opt-in, but
+ // an analysis of all of them is a future FIXME.
+ if (CausesMV && OldFD && HasNonMultiVersionAttributes(OldFD, MVType)) {
+ S.Diag(OldFD->getLocation(), diag::err_multiversion_no_other_attrs)
+ << IsCPUSpecificCPUDispatchMVType;
+ S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
+ return true;
+ }
+
+ if (HasNonMultiVersionAttributes(NewFD, MVType))
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_no_other_attrs)
+ << IsCPUSpecificCPUDispatchMVType;
+
+ // Only allow transition to MultiVersion if it hasn't been used.
+ if (OldFD && CausesMV && OldFD->isUsed(false))
+ return S.Diag(NewFD->getLocation(), diag::err_multiversion_after_used);
+
+ return S.areMultiversionVariantFunctionsCompatible(
+ OldFD, NewFD, S.PDiag(diag::err_multiversion_noproto),
+ PartialDiagnosticAt(NewFD->getLocation(),
+ S.PDiag(diag::note_multiversioning_caused_here)),
+ PartialDiagnosticAt(NewFD->getLocation(),
+ S.PDiag(diag::err_multiversion_doesnt_support)
+ << IsCPUSpecificCPUDispatchMVType),
+ PartialDiagnosticAt(NewFD->getLocation(),
+ S.PDiag(diag::err_multiversion_diff)),
+ /*TemplatesSupported=*/false,
+ /*ConstexprSupported=*/!IsCPUSpecificCPUDispatchMVType);
+}
+
/// Check the validity of a multiversion function declaration that is the
/// first of its kind. Also sets the multiversion'ness' of the function itself.
///
Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=371892&r1=371891&r2=371892&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Fri Sep 13 13:18:17 2019
@@ -3447,6 +3447,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMP
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_requires:
+ case OMPD_declare_variant:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -4516,6 +4517,7 @@ StmtResult Sema::ActOnOpenMPExecutableDi
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_requires:
+ case OMPD_declare_variant:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -4653,8 +4655,10 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDe
if (!DG || DG.get().isNull())
return DeclGroupPtrTy();
+ const int SimdId = 0;
if (!DG.get().isSingleDecl()) {
- Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd);
+ Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
+ << SimdId;
return DG;
}
Decl *ADecl = DG.get().getSingleDecl();
@@ -4663,7 +4667,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDe
auto *FD = dyn_cast<FunctionDecl>(ADecl);
if (!FD) {
- Diag(ADecl->getLocation(), diag::err_omp_function_expected);
+ Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
return DeclGroupPtrTy();
}
@@ -4888,6 +4892,204 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDe
return ConvertDeclToDeclGroup(ADecl);
}
+Sema::DeclGroupPtrTy
+Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
+ Expr *VariantRef, SourceRange SR) {
+ if (!DG || DG.get().isNull())
+ return DeclGroupPtrTy();
+
+ const int VariantId = 1;
+ // Must be applied only to single decl.
+ if (!DG.get().isSingleDecl()) {
+ Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
+ << VariantId << SR;
+ return DG;
+ }
+ Decl *ADecl = DG.get().getSingleDecl();
+ if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
+ ADecl = FTD->getTemplatedDecl();
+
+ // Decl must be a function.
+ auto *FD = dyn_cast<FunctionDecl>(ADecl);
+ if (!FD) {
+ Diag(ADecl->getLocation(), diag::err_omp_function_expected)
+ << VariantId << SR;
+ return DeclGroupPtrTy();
+ }
+
+ auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
+ return FD->hasAttrs() &&
+ (FD->hasAttr<CPUDispatchAttr>() || FD->hasAttr<CPUSpecificAttr>() ||
+ FD->hasAttr<TargetAttr>());
+ };
+ // OpenMP is not compatible with CPU-specific attributes.
+ if (HasMultiVersionAttributes(FD)) {
+ Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
+ << SR;
+ return DG;
+ }
+
+ // Allow #pragma omp declare variant only if the function is not used.
+ if (FD->isUsed(false)) {
+ Diag(SR.getBegin(), diag::err_omp_declare_variant_after_used)
+ << FD->getLocation();
+ return DG;
+ }
+
+ // The VariantRef must point to function.
+ if (!VariantRef) {
+ Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
+ return DG;
+ }
+
+ // Do not check templates, wait until instantiation.
+ if (VariantRef->isTypeDependent() || VariantRef->isValueDependent() ||
+ VariantRef->containsUnexpandedParameterPack() ||
+ VariantRef->isInstantiationDependent() || FD->isDependentContext())
+ return DG;
+
+ // Convert VariantRef expression to the type of the original function to
+ // resolve possible conflicts.
+ ExprResult VariantRefCast;
+ if (LangOpts.CPlusPlus) {
+ QualType FnPtrType;
+ auto *Method = dyn_cast<CXXMethodDecl>(FD);
+ if (Method && !Method->isStatic()) {
+ const Type *ClassType =
+ Context.getTypeDeclType(Method->getParent()).getTypePtr();
+ FnPtrType = Context.getMemberPointerType(FD->getType(), ClassType);
+ ExprResult ER;
+ {
+ // Build adrr_of unary op to correctly handle type checks for member
+ // functions.
+ Sema::TentativeAnalysisScope Trap(*this);
+ ER = CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
+ VariantRef);
+ }
+ if (!ER.isUsable()) {
+ Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
+ << VariantId << VariantRef->getSourceRange();
+ return DG;
+ }
+ VariantRef = ER.get();
+ } else {
+ FnPtrType = Context.getPointerType(FD->getType());
+ }
+ ImplicitConversionSequence ICS =
+ TryImplicitConversion(VariantRef, FnPtrType.getUnqualifiedType(),
+ /*SuppressUserConversions=*/false,
+ /*AllowExplicit=*/false,
+ /*InOverloadResolution=*/false,
+ /*CStyle=*/false,
+ /*AllowObjCWritebackConversion=*/false);
+ if (ICS.isFailure()) {
+ Diag(VariantRef->getExprLoc(),
+ diag::err_omp_declare_variant_incompat_types)
+ << VariantRef->getType() << FnPtrType << VariantRef->getSourceRange();
+ return DG;
+ }
+ VariantRefCast = PerformImplicitConversion(
+ VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
+ if (!VariantRefCast.isUsable())
+ return DG;
+ // Drop previously built artificial addr_of unary op for member functions.
+ if (Method && !Method->isStatic()) {
+ Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
+ if (auto *UO = dyn_cast<UnaryOperator>(
+ PossibleAddrOfVariantRef->IgnoreImplicit()))
+ VariantRefCast = UO->getSubExpr();
+ }
+ } else {
+ VariantRefCast = VariantRef;
+ }
+
+ ExprResult ER = CheckPlaceholderExpr(VariantRefCast.get());
+ if (!ER.isUsable() ||
+ !ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
+ Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
+ << VariantId << VariantRef->getSourceRange();
+ return DG;
+ }
+
+ // The VariantRef must point to function.
+ auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
+ if (!DRE) {
+ Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
+ << VariantId << VariantRef->getSourceRange();
+ return DG;
+ }
+ auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
+ if (!NewFD) {
+ Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
+ << VariantId << VariantRef->getSourceRange();
+ return DG;
+ }
+
+ enum DoesntSupport {
+ VirtFuncs = 1,
+ Constructors = 3,
+ Destructors = 4,
+ DeletedFuncs = 5,
+ DefaultedFuncs = 6,
+ ConstexprFuncs = 7,
+ ConstevalFuncs = 8,
+ };
+ if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (CXXFD->isVirtual()) {
+ Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
+ << VirtFuncs;
+ return DG;
+ }
+
+ if (isa<CXXConstructorDecl>(FD)) {
+ Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
+ << Constructors;
+ return DG;
+ }
+
+ if (isa<CXXDestructorDecl>(FD)) {
+ Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
+ << Destructors;
+ return DG;
+ }
+ }
+
+ if (FD->isDeleted()) {
+ Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
+ << DeletedFuncs;
+ return DG;
+ }
+
+ if (FD->isDefaulted()) {
+ Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
+ << DefaultedFuncs;
+ return DG;
+ }
+
+ if (FD->isConstexpr()) {
+ Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
+ << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
+ return DG;
+ }
+
+ // Check general compatibility.
+ if (areMultiversionVariantFunctionsCompatible(
+ FD, NewFD, PDiag(diag::err_omp_declare_variant_noproto),
+ PartialDiagnosticAt(
+ SR.getBegin(),
+ PDiag(diag::note_omp_declare_variant_specified_here) << SR),
+ PartialDiagnosticAt(
+ VariantRef->getExprLoc(),
+ PDiag(diag::err_omp_declare_variant_doesnt_support)),
+ PartialDiagnosticAt(VariantRef->getExprLoc(),
+ PDiag(diag::err_omp_declare_variant_diff)
+ << FD->getLocation()),
+ /*TemplatesSupported=*/true, /*ConstexprSupported=*/false))
+ return DG;
+
+ return DG;
+}
+
StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
@@ -9895,6 +10097,7 @@ static OpenMPDirectiveKind getOpenMPCapt
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_teams:
@@ -9963,6 +10166,7 @@ static OpenMPDirectiveKind getOpenMPCapt
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_teams:
@@ -10032,6 +10236,7 @@ static OpenMPDirectiveKind getOpenMPCapt
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@@ -10098,6 +10303,7 @@ static OpenMPDirectiveKind getOpenMPCapt
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@@ -10165,6 +10371,7 @@ static OpenMPDirectiveKind getOpenMPCapt
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@@ -10231,6 +10438,7 @@ static OpenMPDirectiveKind getOpenMPCapt
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
@@ -10296,6 +10504,7 @@ static OpenMPDirectiveKind getOpenMPCapt
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
+ case OMPD_declare_variant:
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_simd:
Added: cfe/trunk/test/OpenMP/declare_variant_messages.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_variant_messages.c?rev=371892&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/declare_variant_messages.c (added)
+++ cfe/trunk/test/OpenMP/declare_variant_messages.c Fri Sep 13 13:18:17 2019
@@ -0,0 +1,92 @@
+// 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
+
+// expected-error at +1 {{expected an OpenMP directive}}
+#pragma omp declare
+
+int foo(void);
+
+#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
+#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare variant(foo // expected-error {{expected ')'}} expected-error {{expected 'match' clause on 'omp declare variant' directive}} expected-note {{to match this '('}}
+#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}}
+#pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foo) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foo) match // expected-error {{expected '(' after 'match'}}
+#pragma omp declare variant(foo) match( // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foo) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foo) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}}
+#pragma omp declare variant(foo) match(xxx=) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foo) match(xxx=yyy) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foo) match(xxx=yyy}) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foo) match(xxx={) // expected-error {{expected '}'}} expected-note {{to match this '{'}}
+#pragma omp declare variant(foo) match(xxx={})
+#pragma omp declare variant(foo) match(xxx={vvv})
+#pragma omp declare variant(foo) match(xxx={vvv} xxx) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare variant(foo) match(xxx={vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+int bar(void);
+
+// expected-error at +2 {{'#pragma omp declare variant' can only be applied to functions}}
+#pragma omp declare variant(foo) match(xxx={})
+int a;
+// expected-error at +2 {{'#pragma omp declare variant' can only be applied to functions}}
+#pragma omp declare variant(foo) match(xxx={})
+#pragma omp threadprivate(a)
+int var;
+#pragma omp threadprivate(var)
+
+// expected-error at +2 {{expected an OpenMP directive}} expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(foo) match(xxx={})
+#pragma omp declare
+
+// expected-error at +3 {{function declaration is expected after 'declare variant' directive}}
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(foo) match(xxx={})
+#pragma omp declare variant(foo) match(xxx={})
+#pragma options align=packed
+int main();
+
+// expected-error at +3 {{function declaration is expected after 'declare variant' directive}}
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(foo) match(xxx={})
+#pragma omp declare variant(foo) match(xxx={})
+#pragma init_seg(compiler)
+int main();
+
+// expected-error at +1 {{single declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(foo) match(xxx={})
+int b, c;
+
+int no_proto();
+
+// expected-error at +3 {{function with '#pragma omp declare variant' must have a prototype}}
+// expected-note at +1 {{'#pragma omp declare variant' for function specified here}}
+#pragma omp declare variant(no_proto) match(xxx={})
+int no_proto_too();
+
+int after_use_variant(void);
+int after_use();
+int bar() {
+ return after_use();
+}
+
+// expected-error at +1 {{'#pragma omp declare variant' cannot be applied for function after first usage}}
+#pragma omp declare variant(after_use_variant) match(xxx={})
+int after_use(void);
+
+int diff_cc_variant(void);
+// expected-error at +1 {{function with '#pragma omp declare variant' has a different calling convention}}
+#pragma omp declare variant(diff_cc_variant) match(xxx={})
+__vectorcall int diff_cc(void);
+
+int diff_ret_variant(void);
+// expected-error at +1 {{function with '#pragma omp declare variant' has a different return type}}
+#pragma omp declare variant(diff_ret_variant) match(xxx={})
+void diff_ret(void);
+
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant
Added: cfe/trunk/test/OpenMP/declare_variant_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/declare_variant_messages.cpp?rev=371892&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/declare_variant_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/declare_variant_messages.cpp Fri Sep 13 13:18:17 2019
@@ -0,0 +1,225 @@
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c++ -std=c++14 -fms-extensions -Wno-pragma-pack -fexceptions -fcxx-exceptions %s
+
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c++ -std=c++14 -fms-extensions -Wno-pragma-pack -fexceptions -fcxx-exceptions %s
+
+// expected-error at +1 {{expected an OpenMP directive}}
+#pragma omp declare
+
+int foo();
+
+template <typename T>
+T foofoo();
+
+#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
+#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare variant(foo // expected-error {{expected ')'}} expected-error {{expected 'match' clause on 'omp declare variant' directive}} expected-note {{to match this '('}}
+#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}}
+#pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <int>) // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <int>) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <int>) match // expected-error {{expected '(' after 'match'}}
+#pragma omp declare variant(foofoo <int>) match( // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <int>) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foofoo <int>) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}}
+#pragma omp declare variant(foofoo <int>) match(xxx =) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foofoo <int>) match(xxx = yyy) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foofoo <int>) match(xxx = yyy }) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foofoo <int>) match(xxx = {) // expected-error {{expected '}'}} expected-note {{to match this '{'}}
+#pragma omp declare variant(foofoo <int>) match(xxx = {})
+#pragma omp declare variant(foofoo <int>) match(xxx = {vvv})
+#pragma omp declare variant(foofoo <int>) match(xxx = {vvv} xxx) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare variant(foofoo <int>) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+int bar();
+
+#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
+#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare variant(foofoo <T> // expected-error {{expected ')'}} expected-error {{expected 'match' clause on 'omp declare variant' directive}} expected-note {{to match this '('}}
+#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}}
+#pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <T>) // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <T>) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <T>) match // expected-error {{expected '(' after 'match'}}
+#pragma omp declare variant(foofoo <T>) match( // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <T>) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foofoo <T>) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}}
+#pragma omp declare variant(foofoo <T>) match(xxx =) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foofoo <T>) match(xxx = {) // expected-error {{expected '}'}} expected-note {{to match this '{'}}
+#pragma omp declare variant(foofoo <T>) match(xxx = {})
+#pragma omp declare variant(foofoo <T>) match(xxx = {vvv})
+#pragma omp declare variant(foofoo <T>) match(user = {score(<expr>) : condition(<expr>)})
+#pragma omp declare variant(foofoo <T>) match(user = {score(<expr>) : condition(<expr>)})
+#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)})
+#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)})
+#pragma omp declare variant(foofoo <T>) match(xxx = {vvv} xxx) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare variant(foofoo <T>) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+template <typename T>
+T barbar();
+
+// expected-error at +2 {{'#pragma omp declare variant' can only be applied to functions}}
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+int a;
+// expected-error at +2 {{'#pragma omp declare variant' can only be applied to functions}}
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+#pragma omp threadprivate(a)
+int var;
+#pragma omp threadprivate(var)
+
+// expected-error at +2 {{expected an OpenMP directive}} expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+#pragma omp declare
+
+// expected-error at +3 {{function declaration is expected after 'declare variant' directive}}
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+#pragma options align = packed
+int main();
+
+// expected-error at +3 {{function declaration is expected after 'declare variant' directive}}
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+#pragma init_seg(compiler)
+int main();
+
+// expected-error at +1 {{single declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+int b, c;
+
+// expected-error at +1 {{'C' does not refer to a value}}
+#pragma omp declare variant(C) match(xxx = {})
+// expected-note at +1 {{declared here}}
+template <class C>
+void h(C *hp, C *hp2, C *hq, C *lin) {
+ b = 0;
+}
+
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type '<overloaded function type>' is incompatible with type 'void (*)(int *, int *, int *, int *)'}}
+#pragma omp declare variant(barbar <int>) match(xxx = {})
+template <>
+void h(int *hp, int *hp2, int *hq, int *lin) {
+ h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
+}
+
+int after_use_variant(void);
+int after_use();
+int bar() {
+ return after_use();
+}
+
+// expected-error at +1 {{'#pragma omp declare variant' cannot be applied for function after first usage}}
+#pragma omp declare variant(after_use_variant) match(xxx = {})
+int after_use(void);
+
+int fn();
+int fn(int);
+#pragma omp declare variant(fn) match(xxx = {})
+int overload(void);
+
+int fn1();
+int fn1(int);
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type '<overloaded function type>' is incompatible with type 'int (*)(float)'}}
+#pragma omp declare variant(fn1) match(xxx = {})
+int overload1(float);
+
+int fn_constexpr_variant();
+// expected-error at +2 {{'#pragma omp declare variant' does not support constexpr functions}}
+#pragma omp declare variant(fn_constexpr_variant) match(xxx = {})
+constexpr int fn_constexpr();
+
+constexpr int fn_constexpr_variant1();
+// expected-error at +1 {{'#pragma omp declare variant' does not support constexpr functions}}
+#pragma omp declare variant(fn_constexpr_variant1) match(xxx = {})
+int fn_constexpr1();
+
+int fn_sc_variant();
+// expected-error at +1 {{function with '#pragma omp declare variant' has a different storage class}}
+#pragma omp declare variant(fn_sc_variant) match(xxx = {})
+static int fn_sc();
+
+static int fn_sc_variant1();
+// expected-error at +1 {{function with '#pragma omp declare variant' has a different storage class}}
+#pragma omp declare variant(fn_sc_variant1) match(xxx = {})
+int fn_sc1();
+
+int fn_inline_variant();
+// expected-error at +1 {{function with '#pragma omp declare variant' has a different inline specification}}
+#pragma omp declare variant(fn_inline_variant) match(xxx = {})
+inline int fn_inline();
+
+inline int fn_inline_variant1();
+// expected-error at +1 {{function with '#pragma omp declare variant' has a different inline specification}}
+#pragma omp declare variant(fn_inline_variant1) match(xxx = {})
+int fn_inline1();
+
+int fn_linkage_variant();
+extern "C" {
+// expected-error at +1 {{function with '#pragma omp declare variant' has a different linkage}}
+#pragma omp declare variant(fn_linkage_variant) match(xxx = {})
+int fn_linkage();
+}
+
+extern "C" int fn_linkage_variant1();
+// expected-error at +1 {{function with '#pragma omp declare variant' has a different linkage}}
+#pragma omp declare variant(fn_linkage_variant1) match(xxx = {})
+int fn_linkage1();
+
+auto fn_deduced_variant() { return 0; }
+#pragma omp declare variant(fn_deduced_variant) match(xxx = {})
+int fn_deduced();
+
+int fn_deduced_variant1();
+#pragma omp declare variant(fn_deduced_variant1) match(xxx = {})
+auto fn_deduced1() { return 0; }
+
+auto fn_deduced_variant2() { return 0; }
+// expected-error at +1 {{variant in '#pragma omp declare variant' with type 'int ()' is incompatible with type 'float (*)()'}}
+#pragma omp declare variant(fn_deduced_variant2) match(xxx = {})
+float fn_deduced2();
+
+// expected-error at +1 {{exception specification in declaration does not match previous declaration}}
+int fn_except_variant() noexcept(true);
+// expected-note at +2 {{previous declaration is here}}
+#pragma omp declare variant(fn_except_variant) match(xxx = {})
+int fn_except() noexcept(false);
+
+// expected-error at +1 {{exception specification in declaration does not match previous declaration}}
+int fn_except_variant1() noexcept(false);
+// expected-note at +2 {{previous declaration is here}}
+#pragma omp declare variant(fn_except_variant1) match(xxx = {})
+int fn_except1() noexcept(true);
+
+struct SpecialFuncs {
+ void vd();
+ // expected-error at +2 {{'#pragma omp declare variant' does not support constructors}}
+#pragma omp declare variant(SpecialFuncs::vd) match(xxx = {})
+ SpecialFuncs();
+ // expected-error at +2 {{'#pragma omp declare variant' does not support destructors}}
+#pragma omp declare variant(SpecialFuncs::vd) match(xxx = {})
+ ~SpecialFuncs();
+
+ void baz();
+ void bar();
+ void bar(int);
+#pragma omp declare variant(SpecialFuncs::baz) match(xxx = {})
+#pragma omp declare variant(SpecialFuncs::bar) match(xxx = {})
+ void foo1();
+ SpecialFuncs& foo(const SpecialFuncs&);
+ SpecialFuncs& bar(SpecialFuncs&&);
+ // expected-error at +2 {{'#pragma omp declare variant' does not support defaulted functions}}
+#pragma omp declare variant(SpecialFuncs::foo) match(xxx = {})
+ SpecialFuncs& operator=(const SpecialFuncs&) = default;
+ // expected-error at +2 {{'#pragma omp declare variant' does not support deleted functions}}
+#pragma omp declare variant(SpecialFuncs::bar) match(xxx = {})
+ SpecialFuncs& operator=(SpecialFuncs&&) = delete;
+};
+
+namespace N {
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant
+} // namespace N
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant
+// expected-error at +1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant
More information about the cfe-commits
mailing list