[clang] 58b77b8 - [OpenACC] Implement 'bind' clause parsing.

via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 17 14:07:38 PST 2024


Author: erichkeane
Date: 2024-01-17T14:07:34-08:00
New Revision: 58b77b8581989a960bcb3bd088ac4a3e00c9fdb5

URL: https://github.com/llvm/llvm-project/commit/58b77b8581989a960bcb3bd088ac4a3e00c9fdb5
DIFF: https://github.com/llvm/llvm-project/commit/58b77b8581989a960bcb3bd088ac4a3e00c9fdb5.diff

LOG: [OpenACC] Implement 'bind' clause parsing.

'bind' takes either a string literal, or an 'identifier' representing
the device-side function that this routine is intended to 'bind' to
(that is, to call).  However, it seems that the intent is to permit the
'identifier' to reference any function, thus we're implementing this as
an ID expression.

Additionally, while working on this I discovered that the 'routine' ID
expression parsing for C++ wouldn't allow non-static member functions to
be referenced since it expected us to call it, this was fixed as a part
of this patch as the 'bind' support needed it too.  A test was added for
routine.

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticParseKinds.td
    clang/include/clang/Basic/OpenACCKinds.h
    clang/include/clang/Parse/Parser.h
    clang/lib/Parse/ParseOpenACC.cpp
    clang/test/ParserOpenACC/parse-clauses.c
    clang/test/ParserOpenACC/parse-clauses.cpp
    clang/test/ParserOpenACC/parse-constructs.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index bf7156332d52b2..a30ab27566ec3e 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1374,6 +1374,7 @@ def err_acc_expected_reduction_operator
 def err_acc_invalid_reduction_operator
     : Error<"invalid reduction operator,  expected '+', '*', 'max', 'min', "
             "'&', '|', '^', '&&', or '||'">;
+def err_acc_incorrect_bind_arg : Error<"expected identifier or string literal">;
 
 // OpenMP support.
 def warn_pragma_omp_ignored : Warning<

diff  --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 16cee08e4d8fce..a27b78d2e6da8e 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -219,6 +219,8 @@ enum class OpenACCClauseKind {
   Reduction,
   /// 'collapse' clause, allowed on 'loop' and Combined constructs.
   Collapse,
+  /// 'bind' clause, allowed on routine constructs.
+  Bind,
 
   /// Represents an invalid clause, for the purposes of parsing.
   Invalid,
@@ -317,6 +319,9 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
   case OpenACCClauseKind::Collapse:
     return Out << "collapse";
 
+  case OpenACCClauseKind::Bind:
+    return Out << "bind";
+
   case OpenACCClauseKind::Invalid:
     return Out << "<invalid>";
   }

diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 0b14c9aa545459..9e2b452cbe0517 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3581,6 +3581,9 @@ class Parser : public CodeCompletionHandler {
   /// Parses the clause-list for an OpenACC directive.
   void ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
   bool ParseOpenACCWaitArgument();
+  /// Parses the clause of the 'bind' argument, which can be a string literal or
+  /// an ID expression.
+  ExprResult ParseOpenACCBindClauseArgument();
 
 private:
   //===--------------------------------------------------------------------===//

diff  --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 7ff52f040330d3..1f6d111f3aa573 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -91,6 +91,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
              Tok.getIdentifierInfo()->getName())
       .Case("attach", OpenACCClauseKind::Attach)
       .Case("auto", OpenACCClauseKind::Auto)
+      .Case("bind", OpenACCClauseKind::Bind)
       .Case("create", OpenACCClauseKind::Create)
       .Case("collapse", OpenACCClauseKind::Collapse)
       .Case("copy", OpenACCClauseKind::Copy)
@@ -467,6 +468,7 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
   case OpenACCClauseKind::Host:
   case OpenACCClauseKind::Reduction:
   case OpenACCClauseKind::Collapse:
+  case OpenACCClauseKind::Bind:
     return ClauseParensKind::Required;
 
   case OpenACCClauseKind::Auto:
@@ -668,6 +670,12 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
         return true;
       break;
     }
+    case OpenACCClauseKind::Bind: {
+      ExprResult BindArg = ParseOpenACCBindClauseArgument();
+      if (BindArg.isInvalid())
+        return true;
+      break;
+    }
     default:
       llvm_unreachable("Not a required parens type?");
     }
@@ -758,7 +766,7 @@ bool Parser::ParseOpenACCWaitArgument() {
 ExprResult Parser::ParseOpenACCIDExpression() {
   ExprResult Res;
   if (getLangOpts().CPlusPlus) {
-    Res = ParseCXXIdExpression(/*isAddressOfOperand=*/false);
+    Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true);
   } else {
     // There isn't anything quite the same as ParseCXXIdExpression for C, so we
     // need to get the identifier, then call into Sema ourselves.
@@ -785,6 +793,25 @@ ExprResult Parser::ParseOpenACCIDExpression() {
   return getActions().CorrectDelayedTyposInExpr(Res);
 }
 
+ExprResult Parser::ParseOpenACCBindClauseArgument() {
+  // OpenACC 3.3 section 2.15:
+  // The bind clause specifies the name to use when calling the procedure on a
+  // device other than the host. If the name is specified as an identifier, it
+  // is called as if that name were specified in the language being compiled. If
+  // the name is specified as a string, the string is used for the procedure
+  // name unmodified.
+  if (getCurToken().is(tok::r_paren)) {
+    Diag(getCurToken(), diag::err_acc_incorrect_bind_arg);
+    return ExprError();
+  }
+
+  if (tok::isStringLiteral(getCurToken().getKind()))
+    return getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression(
+        /*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true));
+
+  return ParseOpenACCIDExpression();
+}
+
 /// OpenACC 3.3, section 1.6:
 /// In this spec, a 'var' (in italics) is one of the following:
 /// - a variable name (a scalar, array, or compisite variable name)

diff  --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index 336343ecff28f8..22dce4c4d8cd9b 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -706,3 +706,26 @@ void bar();
 
   // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
 #pragma acc routine(bar) worker, vector, seq, nohost
+
+
+// Bind Clause Parsing.
+
+  // expected-error at +2{{expected '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine bind
+void BCP1();
+
+  // expected-error at +2{{expected identifier or string literal}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(BCP1) bind()
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine bind("ReductionClauseParsing")
+void BCP2();
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(BCP1) bind(BCP2)
+
+  // expected-error at +2{{use of undeclared identifier 'unknown_thing'}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(BCP1) bind(unknown_thing)

diff  --git a/clang/test/ParserOpenACC/parse-clauses.cpp b/clang/test/ParserOpenACC/parse-clauses.cpp
index 8771acc6b8eeb7..1b3196094103ca 100644
--- a/clang/test/ParserOpenACC/parse-clauses.cpp
+++ b/clang/test/ParserOpenACC/parse-clauses.cpp
@@ -18,3 +18,56 @@ struct S {
 void use() {
   templ<7, S>();
 }
+
+namespace NS {
+void NSFunc();
+
+class RecordTy { // #RecTy
+  static constexpr bool Value = false; // #VAL
+  void priv_mem_function(); // #PrivMemFun
+  public:
+  static constexpr bool ValuePub = true;
+  void mem_function();
+};
+template<typename T>
+class TemplTy{};
+void function();
+}
+
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::NSFunc)
+  // expected-error at +3{{'RecordTy' does not refer to a value}}
+  // expected-note@#RecTy{{declared here}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::RecordTy)
+  // expected-error at +3{{'Value' is a private member of 'NS::RecordTy'}}
+  // expected-note@#VAL{{implicitly declared private here}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::RecordTy::Value)
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::RecordTy::ValuePub)
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::TemplTy<int>)
+  // expected-error at +2{{no member named 'unknown' in namespace 'NS'}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::unknown<int>)
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::function)
+  // expected-error at +3{{'priv_mem_function' is a private member of 'NS::RecordTy'}}
+  // expected-note@#PrivMemFun{{implicitly declared private here}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::RecordTy::priv_mem_function)
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(NS::RecordTy::mem_function)
+
+  // expected-error at +2{{string literal with user-defined suffix cannot be used here}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind("unknown udl"_UDL)
+
+  // expected-warning at +2{{encoding prefix 'u' on an unevaluated string literal has no effect}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(u"16 bits")
+  // expected-warning at +2{{encoding prefix 'U' on an unevaluated string literal has no effect}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine(use) bind(U"32 bits")

diff  --git a/clang/test/ParserOpenACC/parse-constructs.cpp b/clang/test/ParserOpenACC/parse-constructs.cpp
index f26f9aee8546b4..abeddd357619e0 100644
--- a/clang/test/ParserOpenACC/parse-constructs.cpp
+++ b/clang/test/ParserOpenACC/parse-constructs.cpp
@@ -5,6 +5,12 @@ namespace NS {
 
   template<typename T>
   void templ(); // expected-note 2{{declared here}}
+
+  class C { // #CDef
+    void private_mem_func(); // #PrivateMemFunc
+    public:
+    void public_mem_func();
+  };
 }
 
 // expected-error at +2{{use of undeclared identifier 'foo'; did you mean 'NS::foo'?}}
@@ -44,3 +50,14 @@ namespace NS {
 // expected-error at +2 {{expected unqualified-id}}
 // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
 #pragma acc routine(int)
+
+// expected-error at +3{{'C' does not refer to a value}}
+// expected-note@#CDef{{declared here}}
+// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine (NS::C)
+// expected-error at +3{{'private_mem_func' is a private member of 'NS::C'}}
+// expected-note@#PrivateMemFunc{{implicitly declared private here}}
+// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine (NS::C::private_mem_func)
+// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc routine (NS::C::public_mem_func)


        


More information about the cfe-commits mailing list