andwar updated this revision to Diff 219673.
andwar marked 6 inline comments as done.
andwar added a comment.

- Removed `declare variant` from Attr.td
- Moved the 'vector-var-id' lookup from ParseOpenMP.cpp to SemaOpenMP.cpp
- Parsing 'vector-var-id' as an expression
- Removed the creation of the attribute in `ActOnOpenMPDeclareVariantDirective`


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67294/new/

https://reviews.llvm.org/D67294

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/OpenMPKinds.def
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/Basic/OpenMPKinds.cpp
  lib/CodeGen/CGOpenMPRuntime.cpp
  lib/Parse/ParseOpenMP.cpp
  lib/Sema/SemaOpenMP.cpp
  test/OpenMP/declare_variant_messages.cpp

Index: test/OpenMP/declare_variant_messages.cpp
===================================================================
--- /dev/null
+++ test/OpenMP/declare_variant_messages.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c++ -std=c++11 -fms-extensions -Wno-pragma-pack %s
+
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c++ -std=c++11 -fms-extensions -Wno-pragma-pack %s
+
+// The dummy vector variant
+void vector_foo();
+
+//=============================================================================
+// Basic errors
+//=============================================================================
+// This is (and should be) perfectly fine for the parser, although semantically
+// not valid OpenMP 5.
+#pragma omp declare variant(vector_foo)
+void foo();
+
+// expected-error@+1 {{expected an OpenMP directive}}
+#pragma omp declare
+
+// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}}
+#pragma omp declare variant(vector_foo)
+int a;
+// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}}
+#pragma omp declare variant (vector_foo)
+#pragma omp threadprivate(a)
+int var;
+#pragma omp threadprivate(var)
+
+// expected-error@+3 {{expected an OpenMP directive}}
+// expected-error@+1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant
+#pragma omp declare
+
+// expected-error@+1 {{single declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant(vector_foo)
+int b, c;
+
+//=============================================================================
+// Syntax/semantic error: everything excluding linear/aligned/uniform
+//=============================================================================
+// expected-error@+1 {{expected an OpenMP directive}}
+#pragma omp variant
+// expected-error@+1 {{expected '(' after '#pragma omp declare variant'}}
+#pragma omp declare variant
+// expected-warning@+2 {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+// expected-error@+1 {{expected '(' after '#pragma omp declare variant'}}
+#pragma omp declare variant )
+// expected-error@+1 {{expected unqualified-id representing 'vector-variant-id'}}
+#pragma omp declare variant()
+// expected-error@+1 {{no declaration for 'undeclared_func', only declared functions can be used as <vector-variant-id>}}
+#pragma omp declare variant(undeclared_func)
+// expected-error@+2 {{expected ')'}}
+// expected-note@+1 {{to match this '('}}
+#pragma omp declare variant(vector_foo
+void foo();
+
+//=============================================================================
+// Templates
+//=============================================================================
+// expected-error@+1 {{'#pragma omp declare variant' can only be used to decorate instantiated templates}}
+#pragma omp declare variant(vector_foo)
+template <class C>
+void h(C *hp, C *hp2, C *hq, C *lin) {
+  b = 0;
+}
+
+#pragma omp declare variant(vector_foo)
+template <>
+void h(int *hp, int *hp2, int *hq, int *lin) {
+  h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
+}
+
+//=============================================================================
+// 'declare variant' embedded in namespaces
+//=============================================================================
+namespace N {
+  // expected-error@+1 {{function declaration is expected after 'declare variant' directive}}
+  #pragma omp declare variant
+}
+// expected-error@+1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant
+// Now verify that the parser recovered fine from the previous error and identifies another one correctly
+// expected-error@+1 {{function declaration is expected after 'declare variant' directive}}
+#pragma omp declare variant
Index: lib/Sema/SemaOpenMP.cpp
===================================================================
--- lib/Sema/SemaOpenMP.cpp
+++ lib/Sema/SemaOpenMP.cpp
@@ -3438,6 +3438,7 @@
   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_requires:
@@ -4506,6 +4507,7 @@
   case OMPD_declare_reduction:
   case OMPD_declare_mapper:
   case OMPD_declare_simd:
+  case OMPD_declare_variant:
   case OMPD_requires:
     llvm_unreachable("OpenMP Directive is not allowed");
   case OMPD_unknown:
@@ -4645,7 +4647,8 @@
     return DeclGroupPtrTy();
 
   if (!DG.get().isSingleDecl()) {
-    Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd);
+    Diag(SR.getBegin(), diag::err_omp_single_decl_after_declare_directive)
+        << /*declare simd*/ 0;
     return DG;
   }
   Decl *ADecl = DG.get().getSingleDecl();
@@ -4654,7 +4657,8 @@
 
   auto *FD = dyn_cast<FunctionDecl>(ADecl);
   if (!FD) {
-    Diag(ADecl->getLocation(), diag::err_omp_function_expected);
+    Diag(ADecl->getLocation(), diag::err_omp_function_expected)
+        << /*declare simd*/ 0;
     return DeclGroupPtrTy();
   }
 
@@ -4879,6 +4883,51 @@
   return ConvertDeclToDeclGroup(ADecl);
 }
 
+Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareVariantDirective(
+    DeclGroupPtrTy DG, UnqualifiedId &VectorVariantId, SourceRange SR) {
+  assert(!DG.get().isNull() && "Missing function declaration after pragma");
+
+  // '#pragma omp declare variant' is only allowed for template instantiations.
+  // It's meaning for template declarations would be ambigous.
+  Decl *D = *DG.get().begin();
+  if (D->isTemplateDecl()) {
+    Diag(SR.getBegin(), diag::err_omp_declare_variant_template_decl);
+    return DG;
+  }
+
+  if (!DG.get().isSingleDecl()) {
+    Diag(SR.getBegin(), diag::err_omp_single_decl_after_declare_directive)
+        << /*declare variant*/ 1;
+    return DG;
+  }
+
+  Decl *ADecl = DG.get().getSingleDecl();
+  if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
+    ADecl = FTD->getTemplatedDecl();
+
+  auto *FD = dyn_cast<FunctionDecl>(ADecl);
+  if (!FD) {
+    Diag(ADecl->getLocation(), diag::err_omp_function_expected)
+        << /*declare variant*/ 1;
+    return DeclGroupPtrTy();
+  }
+
+  // Look up for the declaration of the variant.
+  StringRef FuncName = VectorVariantId.Identifier->getName();
+  DeclarationName VecVarDN(VectorVariantId.Identifier);
+  NamedDecl *VecVarND = LookupSingleName(getCurScope(), VecVarDN, SR.getBegin(),
+                                         Sema::LookupOrdinaryName);
+
+  // If the declaration of the variant is found, add the
+  // attribute. Otherwise, raise an error.
+  if (nullptr == VecVarND)
+    Diag(VectorVariantId.getBeginLoc(),
+         diag::err_omp_expected_declared_func_ident)
+        << VectorVariantId.Identifier->getName();
+
+  return ConvertDeclToDeclGroup(ADecl);
+}
+
 StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
                                               Stmt *AStmt,
                                               SourceLocation StartLoc,
@@ -9885,6 +9934,7 @@
     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:
@@ -9953,6 +10003,7 @@
     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:
@@ -10022,6 +10073,7 @@
     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:
@@ -10088,6 +10140,7 @@
     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:
@@ -10155,6 +10208,7 @@
     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:
@@ -10221,6 +10275,7 @@
     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:
@@ -10286,6 +10341,7 @@
     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:
Index: lib/Parse/ParseOpenMP.cpp
===================================================================
--- lib/Parse/ParseOpenMP.cpp
+++ lib/Parse/ParseOpenMP.cpp
@@ -38,6 +38,7 @@
   OMPD_target_enter,
   OMPD_target_exit,
   OMPD_update,
+  OMPD_variant,
   OMPD_distribute_parallel,
   OMPD_teams_distribute_parallel,
   OMPD_target_teams_distribute_parallel,
@@ -80,6 +81,7 @@
       .Case("reduction", OMPD_reduction)
       .Case("update", OMPD_update)
       .Case("mapper", OMPD_mapper)
+      .Case("variant", OMPD_variant)
       .Default(OMPD_unknown);
 }
 
@@ -92,6 +94,7 @@
       {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
       {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
       {OMPD_declare, OMPD_simd, OMPD_declare_simd},
+      {OMPD_declare, OMPD_variant, OMPD_declare_variant},
       {OMPD_declare, OMPD_target, OMPD_declare_target},
       {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
       {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
@@ -743,6 +746,46 @@
   return IsError;
 }
 
+/// Parses clauses for 'declare variant' directive.
+///   (vec-var-id) match(context-selector-specification)
+///    context-selector-specification:
+///    TODO Add support for matching context selector
+///
+/// Returns 'true' if there were syntax errors, 'false' otherwise.
+/// Note that similar method for '#pragma omp simd' is _not_ a member of the
+/// Parser -  it's a static function local to this file instead. However, this
+/// method accesses the internals of the Parser, so it makes more sense to
+/// make it a member.
+bool Parser::parseDeclareVariantClauses(UnqualifiedId &VectorVariantId) {
+  const Token &Tok = getCurToken();
+
+  // Parse (variant-func-id)
+  BalancedDelimiterTracker VecVarLeftParen(*this, tok::l_paren);
+  if (!Tok.is(tok::l_paren)) {
+    Diag(Tok, diag::err_expected_lparen_after) << "#pragma omp declare variant";
+    return true;
+  }
+  VecVarLeftParen.consumeOpen();
+
+  if (Tok.isNot(tok::identifier)) {
+    Diag(Tok, diag::err_omp_expected_unqualified_declare_variant_id);
+    SkipUntil(tok::r_paren, StopAtSemi);
+    return true;
+  }
+
+  CXXScopeSpec SS;
+  ParseUnqualifiedId(SS, /*EnteringContext*/ false,
+                     /*AllowDestructorName*/ false,
+                     /*AllowConstructorName*/ false,
+                     /*AllowDeductionGuide*/ false, nullptr, nullptr,
+                     VectorVariantId);
+
+  if (VecVarLeftParen.consumeClose())
+    return true;
+
+  return false;
+}
+
 /// Parse clauses for '#pragma omp declare simd'.
 Parser::DeclGroupPtrTy
 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
@@ -782,6 +825,34 @@
       LinModifiers, Steps, SourceRange(Loc, EndLoc));
 }
 
+/// Parse clauses for '#pragma omp declare variant'
+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);
+
+  FNContextRAII FnContext(*this, Ptr);
+  UnqualifiedId VectorVariantId;
+  bool IsError = parseDeclareVariantClauses(VectorVariantId);
+  // 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, VectorVariantId,
+                                                    SourceRange(Loc, EndLoc));
+}
+
 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
 ///
 ///    default-clause:
@@ -1103,7 +1174,16 @@
     }
     break;
   }
-  case OMPD_declare_simd: {
+  case OMPD_declare_simd:
+    LLVM_FALLTHROUGH;
+  case OMPD_declare_variant: {
+    // The syntax is:
+    // { #pragma omp declare simd }
+    // <function-declaration-or-definition>
+    // and:
+    // { #pragma omp declare variant }
+    // <function-declaration-or-definition>
+    //
     // The syntax is:
     // { #pragma omp declare simd }
     // <function-declaration-or-definition>
@@ -1133,10 +1213,13 @@
       }
     }
     if (!Ptr) {
-      Diag(Loc, diag::err_omp_decl_in_declare_simd);
+      unsigned directive = (OMPD_declare_simd == DKind) ? 0 : 1;
+      Diag(Loc, diag::err_omp_decl_after_declare_directive) << directive;
       return DeclGroupPtrTy();
     }
-    return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
+    return (OMPD_declare_simd == DKind)
+               ? ParseOMPDeclareSimdClauses(Ptr, Toks, Loc)
+               : ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
   }
   case OMPD_declare_target: {
     SourceLocation DTLoc = ConsumeAnyToken();
@@ -1569,6 +1652,7 @@
     break;
   }
   case OMPD_declare_simd:
+  case OMPD_declare_variant:
   case OMPD_declare_target:
   case OMPD_end_declare_target:
   case OMPD_requires:
Index: lib/CodeGen/CGOpenMPRuntime.cpp
===================================================================
--- lib/CodeGen/CGOpenMPRuntime.cpp
+++ lib/CodeGen/CGOpenMPRuntime.cpp
@@ -9545,6 +9545,7 @@
               CGM, ParentName,
               cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
       break;
+    case OMPD_declare_variant:
     case OMPD_parallel:
     case OMPD_for:
     case OMPD_parallel_for:
@@ -10170,6 +10171,7 @@
       RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
                         : OMPRTL__tgt_target_data_update;
       break;
+    case OMPD_declare_variant:
     case OMPD_parallel:
     case OMPD_for:
     case OMPD_parallel_for:
Index: lib/Basic/OpenMPKinds.cpp
===================================================================
--- lib/Basic/OpenMPKinds.cpp
+++ lib/Basic/OpenMPKinds.cpp
@@ -838,6 +838,7 @@
       break;
     }
     break;
+  case OMPD_declare_variant:
   case OMPD_declare_target:
   case OMPD_end_declare_target:
   case OMPD_unknown:
@@ -1075,6 +1076,7 @@
   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_requires:
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -9477,6 +9477,11 @@
       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.
+  DeclGroupPtrTy ActOnOpenMPDeclareVariantDirective(
+      DeclGroupPtrTy DG, UnqualifiedId &VectorVariantId, SourceRange SR);
+
   OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
                                          Expr *Expr,
                                          SourceLocation StartLoc,
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -2834,6 +2834,11 @@
   DeclGroupPtrTy ParseOMPDeclareSimdClauses(DeclGroupPtrTy Ptr,
                                             CachedTokens &Toks,
                                             SourceLocation Loc);
+  /// Parse clauses for '#pragma omp declare variant'.
+  DeclGroupPtrTy ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr,
+                                               CachedTokens &Toks,
+                                               SourceLocation Loc);
+  bool parseDeclareVariantClauses(UnqualifiedId &VectorVariantId);
   /// Parse clauses for '#pragma omp declare target'.
   DeclGroupPtrTy ParseOMPDeclareTargetClauses();
   /// Parse '#pragma omp end declare target'.
Index: include/clang/Basic/OpenMPKinds.def
===================================================================
--- include/clang/Basic/OpenMPKinds.def
+++ include/clang/Basic/OpenMPKinds.def
@@ -236,6 +236,7 @@
 OPENMP_DIRECTIVE(distribute)
 OPENMP_DIRECTIVE_EXT(declare_target, "declare target")
 OPENMP_DIRECTIVE_EXT(end_declare_target, "end declare target")
+OPENMP_DIRECTIVE_EXT(declare_variant, "declare variant")
 OPENMP_DIRECTIVE_EXT(distribute_parallel_for, "distribute parallel for")
 OPENMP_DIRECTIVE_EXT(distribute_parallel_for_simd, "distribute parallel for simd")
 OPENMP_DIRECTIVE_EXT(distribute_simd, "distribute simd")
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -9172,10 +9172,10 @@
   "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_after_declare_directive : 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<
@@ -9367,6 +9367,10 @@
 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_template_decl : Error<
+  "'#pragma omp declare variant' can only be used to decorate instantiated templates">;
+def err_omp_expected_declared_func_ident : Error<
+  "no declaration for '%0', only declared functions can be used as <vector-variant-id>">;
 } // end of OpenMP category
 
 let CategoryName = "Related Result Type Issue" in {
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -1176,8 +1176,8 @@
   "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_after_declare_directive : 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<
@@ -1201,6 +1201,8 @@
 def warn_omp_more_one_device_type_clause : Warning<
   "more than one 'device_type' clause is specified">,
   InGroup<OpenMPClauses>;
+def err_omp_expected_unqualified_declare_variant_id : Error<
+  "expected unqualified-id representing 'vector-variant-id'">;
 
 // Pragma loop support.
 def err_pragma_loop_missing_argument : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to