[clang] e6b7c8c - [OpenACC] Implement 'if' clause

via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 8 07:34:07 PST 2024


Author: erichkeane
Date: 2024-01-08T07:33:28-08:00
New Revision: e6b7c8c4951a470cc63a1721bc5f5ac7f3748a2f

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

LOG: [OpenACC] Implement 'if' clause

The 'if' clause takes a required 'condition' expression.  This patch
implements that as an expression we will later ensure is convertible to
a binary expression.

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 3eb0bf84208fdd..f6a628db29cf48 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -93,6 +93,9 @@ enum class OpenACCClauseKind {
   /// 'default' clause, allowed on parallel, serial, kernel (and compound)
   /// constructs.
   Default,
+  /// 'if' clause, allowed on all the Compute Constructs, Data Constructs,
+  /// Executable Constructs, and Combined Constructs.
+  If,
   /// Represents an invalid clause, for the purposes of parsing.
   Invalid,
 };

diff  --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 94c3d0c4e164cd..84e994ef00816d 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -80,6 +80,10 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
   if (Tok.is(tok::kw_default))
     return OpenACCClauseKind::Default;
 
+  // if is also a keyword, make sure we parse it correctly.
+  if (Tok.is(tok::kw_if))
+    return OpenACCClauseKind::If;
+
   if (!Tok.is(tok::identifier))
     return OpenACCClauseKind::Invalid;
 
@@ -88,6 +92,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
       .Case("auto", OpenACCClauseKind::Auto)
       .Case("default", OpenACCClauseKind::Default)
       .Case("finalize", OpenACCClauseKind::Finalize)
+      .Case("if", OpenACCClauseKind::If)
       .Case("if_present", OpenACCClauseKind::IfPresent)
       .Case("independent", OpenACCClauseKind::Independent)
       .Case("nohost", OpenACCClauseKind::NoHost)
@@ -324,7 +329,7 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
 }
 
 bool ClauseHasRequiredParens(OpenACCClauseKind Kind) {
-  return Kind == OpenACCClauseKind::Default;
+  return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If;
 }
 
 bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
@@ -356,6 +361,19 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
 
       break;
     }
+    case OpenACCClauseKind::If: {
+      // FIXME: It isn't clear if the spec saying 'condition' means the same as
+      // it does in an if/while/etc (See ParseCXXCondition), however as it was
+      // written with Fortran/C in mind, we're going to assume it just means an
+      // 'expression evaluating to boolean'.
+      ExprResult CondExpr =
+          P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression());
+      // An invalid expression can be just about anything, so just give up on
+      // this clause list.
+      if (CondExpr.isInvalid())
+        return true;
+      break;
+    }
     default:
       llvm_unreachable("Not a required parens type?");
     }
@@ -372,8 +390,10 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
 // However, they all are named with a single-identifier (or auto/default!)
 // token, followed in some cases by either braces or parens.
 bool ParseOpenACCClause(Parser &P) {
-  if (!P.getCurToken().isOneOf(tok::identifier, tok::kw_auto, tok::kw_default))
-    return P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
+  // A number of clause names are actually keywords, so accept a keyword that
+  // can be converted to a name.
+  if (expectIdentifierOrKeyword(P))
+    return true;
 
   OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken());
 

diff  --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index aedf0c711ad15b..b247210ff6c764 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -148,8 +148,92 @@ void DefaultClause() {
   // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
 #pragma acc serial default(present), seq
   for(;;){}
+}
+
+void IfClause() {
+  // expected-error at +2{{expected '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial loop if
+  for(;;){}
 
+  // expected-error at +2{{expected '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if seq
+  for(;;){}
+
+  // expected-error at +2{{expected '('}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if, seq
+  for(;;){}
+
+  // expected-error at +2{{expected expression}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(
+  for(;;){}
 
+  // expected-error at +2{{use of undeclared identifier 'seq'}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if( seq
+  for(;;){}
+
+  // expected-error at +3{{expected expression}}
+  // expected-error at +2{{use of undeclared identifier 'seq'}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(, seq
+  for(;;){}
+
+  // expected-error at +3{{expected '('}}
+  // expected-error at +2{{expected identifier}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if)
+  for(;;){}
+
+  // expected-error at +3{{expected '('}}
+  // expected-error at +2{{expected identifier}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if) seq
+  for(;;){}
+
+  // expected-error at +3{{expected '('}}
+  // expected-error at +2{{expected identifier}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if), seq
+  for(;;){}
+
+  // expected-error at +2{{expected expression}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if()
+  for(;;){}
+
+  // expected-error at +2{{expected expression}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if() seq
+  for(;;){}
+
+  // expected-error at +2{{expected expression}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(), seq
+  for(;;){}
+
+  // expected-error at +2{{use of undeclared identifier 'invalid_expr'}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(invalid_expr)
+  for(;;){}
+
+  // expected-error at +2{{expected expression}}
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if() seq
+  for(;;){}
+
+  int i, j;
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(i > j)
+  for(;;){}
+
+  // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(1+5>3), seq
+  for(;;){}
 }
 
   // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}


        


More information about the cfe-commits mailing list