aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerichkeane <ekeane@nvidia.com>2024-01-08 07:12:27 -0800
committererichkeane <ekeane@nvidia.com>2024-01-08 07:33:28 -0800
commite6b7c8c4951a470cc63a1721bc5f5ac7f3748a2f (patch)
treeb69c9047b266edc21ae95da710be60a7fce23c28
parent16cd344380aa89a4bc47939ae65fd59fe8c77181 (diff)
downloadllvm-e6b7c8c4951a470cc63a1721bc5f5ac7f3748a2f.zip
llvm-e6b7c8c4951a470cc63a1721bc5f5ac7f3748a2f.tar.gz
llvm-e6b7c8c4951a470cc63a1721bc5f5ac7f3748a2f.tar.bz2
[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.
-rw-r--r--clang/include/clang/Basic/OpenACCKinds.h3
-rw-r--r--clang/lib/Parse/ParseOpenACC.cpp26
-rw-r--r--clang/test/ParserOpenACC/parse-clauses.c84
3 files changed, 110 insertions, 3 deletions
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 3eb0bf8..f6a628d 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 94c3d0c..84e994e 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 aedf0c7..b247210 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -148,8 +148,92 @@ void DefaultClause() {
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc serial default(present), seq
for(;;){}
+}
+
+void IfClause() {
+ // expected-error@+2{{expected '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial loop if
+ for(;;){}
+ // expected-error@+2{{expected '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if seq
+ for(;;){}
+
+ // expected-error@+2{{expected '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if, seq
+ for(;;){}
+
+ // expected-error@+2{{expected expression}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(
+ for(;;){}
+ // expected-error@+2{{use of undeclared identifier 'seq'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if( seq
+ for(;;){}
+
+ // expected-error@+3{{expected expression}}
+ // expected-error@+2{{use of undeclared identifier 'seq'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(, seq
+ for(;;){}
+
+ // expected-error@+3{{expected '('}}
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if)
+ for(;;){}
+
+ // expected-error@+3{{expected '('}}
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if) seq
+ for(;;){}
+
+ // expected-error@+3{{expected '('}}
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if), seq
+ for(;;){}
+
+ // expected-error@+2{{expected expression}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if()
+ for(;;){}
+
+ // expected-error@+2{{expected expression}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if() seq
+ for(;;){}
+
+ // expected-error@+2{{expected expression}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(), seq
+ for(;;){}
+
+ // expected-error@+2{{use of undeclared identifier 'invalid_expr'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(invalid_expr)
+ for(;;){}
+
+ // expected-error@+2{{expected expression}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if() seq
+ for(;;){}
+
+ int i, j;
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(i > j)
+ for(;;){}
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial if(1+5>3), seq
+ for(;;){}
}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}