diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index a27b78d2e6da8..a33daea2331aa 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -221,6 +221,9 @@ enum class OpenACCClauseKind { Collapse, /// 'bind' clause, allowed on routine constructs. Bind, + /// 'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop', + /// and 'kernels loop' constructs. + VectorLength, /// Represents an invalid clause, for the purposes of parsing. Invalid, @@ -322,6 +325,9 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, case OpenACCClauseKind::Bind: return Out << "bind"; + case OpenACCClauseKind::VectorLength: + return Out << "vector_length"; + case OpenACCClauseKind::Invalid: return Out << ""; } diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 9e2b452cbe051..6bfcd3a0d8412 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3584,7 +3584,9 @@ class Parser : public CodeCompletionHandler { /// Parses the clause of the 'bind' argument, which can be a string literal or /// an ID expression. ExprResult ParseOpenACCBindClauseArgument(); - + /// Parses the clause kind of 'int-expr', which can be any integral + /// expression. + ExprResult ParseOpenACCIntExpr(); private: //===--------------------------------------------------------------------===// // C++ 14: Templates [temp] diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 1f6d111f3aa57..9b0d7077670a7 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -119,6 +119,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) { .Case("seq", OpenACCClauseKind::Seq) .Case("use_device", OpenACCClauseKind::UseDevice) .Case("vector", OpenACCClauseKind::Vector) + .Case("vector_length", OpenACCClauseKind::VectorLength) .Case("worker", OpenACCClauseKind::Worker) .Default(OpenACCClauseKind::Invalid); } @@ -469,6 +470,7 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind, case OpenACCClauseKind::Reduction: case OpenACCClauseKind::Collapse: case OpenACCClauseKind::Bind: + case OpenACCClauseKind::VectorLength: return ClauseParensKind::Required; case OpenACCClauseKind::Auto: @@ -536,6 +538,12 @@ void Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) { } } +ExprResult Parser::ParseOpenACCIntExpr() { + // FIXME: this is required to be an integer expression (or dependent), so we + // should ensure that is the case by passing this to SEMA here. + return getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); +} + bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) { // FIXME: Future clauses will require 'special word' parsing, check for one, // then parse it based on whether it is a clause that requires a 'special @@ -665,7 +673,7 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind, tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Force, Kind); ExprResult NumLoops = - getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + getActions().CorrectDelayedTyposInExpr(ParseConstantExpression()); if (NumLoops.isInvalid()) return true; break; @@ -676,6 +684,12 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind, return true; break; } + case OpenACCClauseKind::VectorLength: { + ExprResult IntExpr = ParseOpenACCIntExpr(); + if (IntExpr.isInvalid()) + return true; + break; + } default: llvm_unreachable("Not a required parens type?"); } diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index 22dce4c4d8cd9..31643073eb76a 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -698,6 +698,33 @@ void ReductionClauseParsing() { #pragma acc serial seq, reduction(&&: Begin, End) // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc serial reduction(||: Begin, End), seq +} + +int returns_int(); + +void IntExprParsing() { + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel vector_length + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel vector_length() + + // expected-error@+2{{use of undeclared identifier 'invalid'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel vector_length(invalid) + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel vector_length(5, 4) + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel vector_length(5) + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel vector_length(returns_int()) } // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} diff --git a/clang/test/ParserOpenACC/parse-clauses.cpp b/clang/test/ParserOpenACC/parse-clauses.cpp index 1b3196094103c..07164b5e33794 100644 --- a/clang/test/ParserOpenACC/parse-clauses.cpp +++ b/clang/test/ParserOpenACC/parse-clauses.cpp @@ -9,6 +9,14 @@ void templ() { // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc loop collapse(T::value) for(;;){} + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel vector_length(T::value) + for(;;){} + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel vector_length(I) + for(;;){} } struct S {