diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index 872faec0deaeb..6487a95910edd 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -232,6 +232,12 @@ enum class OpenACCClauseKind { DeviceNum, /// 'default_async' clause, allowed on 'set' construct. DefaultAsync, + /// 'device_type' clause, allowed on Constructs, 'data', 'init', 'shutdown', + /// 'set', update', 'loop', 'routine', and Combined constructs. + DeviceType, + /// 'dtype' clause, an alias for 'device_type', stored separately for + /// diagnostic purposes. + DType, /// Represents an invalid clause, for the purposes of parsing. Invalid, @@ -348,6 +354,12 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out, case OpenACCClauseKind::DefaultAsync: return Out << "default_async"; + case OpenACCClauseKind::DeviceType: + return Out << "device_type"; + + case OpenACCClauseKind::DType: + return Out << "dtype"; + case OpenACCClauseKind::Invalid: return Out << ""; } diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 6bfcd3a0d8412..ffbde370e8f9c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3587,6 +3587,9 @@ class Parser : public CodeCompletionHandler { /// Parses the clause kind of 'int-expr', which can be any integral /// expression. ExprResult ParseOpenACCIntExpr(); + /// Parses the 'device-type-list', which is a list of identifiers. + bool ParseOpenACCDeviceTypeList(); + private: //===--------------------------------------------------------------------===// // C++ 14: Templates [temp] diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 8020c455feecb..9f7e63ecdc951 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -104,7 +104,9 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) { .Case("device", OpenACCClauseKind::Device) .Case("device_num", OpenACCClauseKind::DeviceNum) .Case("device_resident", OpenACCClauseKind::DeviceResident) + .Case("device_type", OpenACCClauseKind::DeviceType) .Case("deviceptr", OpenACCClauseKind::DevicePtr) + .Case("dtype", OpenACCClauseKind::DType) .Case("finalize", OpenACCClauseKind::Finalize) .Case("firstprivate", OpenACCClauseKind::FirstPrivate) .Case("host", OpenACCClauseKind::Host) @@ -488,6 +490,8 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind, case OpenACCClauseKind::NumWorkers: case OpenACCClauseKind::DeviceNum: case OpenACCClauseKind::DefaultAsync: + case OpenACCClauseKind::DeviceType: + case OpenACCClauseKind::DType: return ClauseParensKind::Required; case OpenACCClauseKind::Auto: @@ -580,6 +584,38 @@ bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) { } return false; } + +/// OpenACC 3.3 Section 2.4: +/// The argument to the device_type clause is a comma-separated list of one or +/// more device architecture name identifiers, or an asterisk. +/// +/// The syntax of the device_type clause is +/// device_type( * ) +/// device_type( device-type-list ) +/// +/// The device_type clause may be abbreviated to dtype. +bool Parser::ParseOpenACCDeviceTypeList() { + + if (expectIdentifierOrKeyword(*this)) { + SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, + Parser::StopBeforeMatch); + return false; + } + ConsumeToken(); + + while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { + ExpectAndConsume(tok::comma); + + if (expectIdentifierOrKeyword(*this)) { + SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, + Parser::StopBeforeMatch); + return false; + } + ConsumeToken(); + } + return false; +} + // The OpenACC Clause List is a comma or space-delimited list of clauses (see // the comment on ParseOpenACCClauseList). The concept of a 'clause' doesn't // really have its owner grammar and each individual one has its own definition. @@ -709,6 +745,16 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind, return true; break; } + case OpenACCClauseKind::DType: + case OpenACCClauseKind::DeviceType: + if (getCurToken().is(tok::star)) { + // FIXME: We want to mark that this is an 'everything else' type of + // device_type in Sema. + ConsumeToken(); + } else if (ParseOpenACCDeviceTypeList()) { + 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 a80173c6eca3d..faf3caa2b1cfd 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -907,6 +907,118 @@ void IntExprParsing() { // expected-error@+2{{invalid tag 'length' on 'worker' clause}} // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} #pragma acc loop worker(length:returns_int()) +} + +void device_type() { + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type + // expected-error@+2{{expected '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype + + // expected-error@+4{{expected identifier}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type( + // expected-error@+4{{expected identifier}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype( + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type() + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype() + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(* + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(* + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(ident + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(ident + + // expected-error@+4{{expected ','}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(ident ident2 + // expected-error@+4{{expected ','}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(ident ident2 + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(ident, ident2 + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(ident, ident2 + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(ident, ident2,) + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(ident, ident2,) + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(*,) + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(*,) + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(*,ident) + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(*,ident) + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(ident, *) + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(ident, *) + + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type("foo", 54) + // expected-error@+2{{expected identifier}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(31, "bar") + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(ident, auto, int, float) + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel dtype(ident, auto, int, float) + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} +#pragma acc parallel device_type(ident, auto, int, float) dtype(ident, auto, int, float) } // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}