diff options
author | erichkeane <ekeane@nvidia.com> | 2024-01-08 07:12:27 -0800 |
---|---|---|
committer | erichkeane <ekeane@nvidia.com> | 2024-01-08 07:33:28 -0800 |
commit | e6b7c8c4951a470cc63a1721bc5f5ac7f3748a2f (patch) | |
tree | b69c9047b266edc21ae95da710be60a7fce23c28 | |
parent | 16cd344380aa89a4bc47939ae65fd59fe8c77181 (diff) | |
download | llvm-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.h | 3 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenACC.cpp | 26 | ||||
-rw-r--r-- | clang/test/ParserOpenACC/parse-clauses.c | 84 |
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}} |