diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index f6a628db29cf4..b0c157e002360 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -96,6 +96,8 @@ enum class OpenACCClauseKind { /// 'if' clause, allowed on all the Compute Constructs, Data Constructs, /// Executable Constructs, and Combined Constructs. If, + /// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'. + Self, /// 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 84e994ef00816..c9224d3ae910c 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -96,6 +96,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) { .Case("if_present", OpenACCClauseKind::IfPresent) .Case("independent", OpenACCClauseKind::Independent) .Case("nohost", OpenACCClauseKind::NoHost) + .Case("self", OpenACCClauseKind::Self) .Case("seq", OpenACCClauseKind::Seq) .Case("vector", OpenACCClauseKind::Vector) .Case("worker", OpenACCClauseKind::Worker) @@ -328,10 +329,22 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) { return DirKind; } +bool ClauseHasOptionalParens(OpenACCClauseKind Kind) { + return Kind == OpenACCClauseKind::Self; +} + bool ClauseHasRequiredParens(OpenACCClauseKind Kind) { return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If; } +ExprResult ParseOpenACCConditionalExpr(Parser &P) { + // 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'. + return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression()); +} + bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) { BalancedDelimiterTracker Parens(P, tok::l_paren, tok::annot_pragma_openacc_end); @@ -362,12 +375,7 @@ 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()); + ExprResult CondExpr = ParseOpenACCConditionalExpr(P); // An invalid expression can be just about anything, so just give up on // this clause list. if (CondExpr.isInvalid()) @@ -379,8 +387,23 @@ bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) { } return Parens.consumeClose(); + } else if (ClauseHasOptionalParens(Kind)) { + if (!Parens.consumeOpen()) { + switch (Kind) { + case OpenACCClauseKind::Self: { + ExprResult CondExpr = ParseOpenACCConditionalExpr(P); + // 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 an optional parens type?"); + } + Parens.consumeClose(); + } } - // FIXME: Handle optional parens return false; } diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index b247210ff6c76..11e89d420e6b0 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -236,6 +236,85 @@ void IfClause() { for(;;){} } +void SyncClause() { + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self + for(;;){} + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self, seq + for(;;){} + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self( + for(;;){} + + // expected-error@+2{{use of undeclared identifier 'seq'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self( 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 loop self(, seq + for(;;){} + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self) + for(;;){} + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self) seq + for(;;){} + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self), seq + for(;;){} + + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self(), seq + for(;;){} + + // expected-error@+3{{expected expression}} + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self(,), seq + for(;;){} + + // expected-error@+2{{use of undeclared identifier 'invalid_expr'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial loop self(invalid_expr), seq + for(;;){} + + int i, j; + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial self(i > j + for(;;){} + + // expected-error@+2{{use of undeclared identifier 'seq'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial self(i > j, seq + for(;;){} + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial self(i > j) + for(;;){} + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc serial self(1+5>3), seq + for(;;){} +} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc routine worker, vector, seq, nohost void bar();