Author: Erich Keane Date: 2023-12-07T17:29:18-08:00 New Revision: df3db035d60ca2471d46166c08208c12307d20ef
URL: https://github.com/llvm/llvm-project/commit/df3db035d60ca2471d46166c08208c12307d20ef DIFF: https://github.com/llvm/llvm-project/commit/df3db035d60ca2471d46166c08208c12307d20ef.diff LOG: [OpenACC] Implement 'wait' construct parsing (#74752) The 'wait' construct comes in two forms: one with no parens, the second with a 'wait-argument'. This implements both forms for constructs. Additionally, the 'wait-argument' parsing is split into its own function because the 'wait clause' can also take the same 'wait-argument'. Added: clang/test/ParserOpenACC/parse-wait-construct.c Modified: clang/include/clang/Basic/OpenACCKinds.h clang/include/clang/Parse/Parser.h clang/lib/Parse/ParseOpenACC.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index 449a75638b43f5..62c0a4c1a9dea4 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -53,7 +53,7 @@ enum class OpenACCDirectiveKind { Shutdown, Set, Update, - // FIXME: wait construct. + Wait, // Procedure Calls in Compute Regions. Routine, diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 32d0b76c35b0d7..06634982351647 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3544,6 +3544,7 @@ class Parser : public CodeCompletionHandler { void ParseOpenACCCacheVarList(); /// Parses a single variable in a variable list for the 'cache' construct. bool ParseOpenACCCacheVar(); + bool ParseOpenACCWaitArgument(); private: //===--------------------------------------------------------------------===// diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 71cb665a563271..40b53dd180c79c 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -56,6 +56,7 @@ OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) { .Case("shutdown", OpenACCDirectiveKind::Shutdown) .Case("set", OpenACCDirectiveKind::Shutdown) .Case("update", OpenACCDirectiveKind::Update) + .Case("wait", OpenACCDirectiveKind::Wait) .Default(OpenACCDirectiveKind::Invalid); if (DirKind != OpenACCDirectiveKind::Invalid) @@ -82,6 +83,24 @@ OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) { .Default(OpenACCAtomicKind::Invalid); } +enum class OpenACCSpecialTokenKind { + DevNum, + Queues, +}; + +bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) { + if (!Tok.is(tok::identifier)) + return false; + + switch (Kind) { + case OpenACCSpecialTokenKind::DevNum: + return Tok.getIdentifierInfo()->isStr("devnum"); + case OpenACCSpecialTokenKind::Queues: + return Tok.getIdentifierInfo()->isStr("queues"); + } + llvm_unreachable("Unknown 'Kind' Passed"); +} + bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { if (!Tok.is(tok::identifier)) return false; @@ -123,6 +142,8 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) { return Tok.getIdentifierInfo()->isStr("set"); case OpenACCDirectiveKind::Update: return Tok.getIdentifierInfo()->isStr("update"); + case OpenACCDirectiveKind::Wait: + return Tok.getIdentifierInfo()->isStr("wait"); case OpenACCDirectiveKind::Invalid: return false; } @@ -251,6 +272,67 @@ void ParseOpenACCClauseList(Parser &P) { } // namespace +/// OpenACC 3.3, section 2.16: +/// In this section and throughout the specification, the term wait-argument +/// means: +/// [ devnum : int-expr : ] [ queues : ] async-argument-list +bool Parser::ParseOpenACCWaitArgument() { + // [devnum : int-expr : ] + if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) && + NextToken().is(tok::colon)) { + // Consume devnum. + ConsumeToken(); + // Consume colon. + ConsumeToken(); + + ExprResult IntExpr = + getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + if (IntExpr.isInvalid()) + return true; + + if (ExpectAndConsume(tok::colon)) + return true; + } + + // [ queues : ] + if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) && + NextToken().is(tok::colon)) { + // Consume queues. + ConsumeToken(); + // Consume colon. + ConsumeToken(); + } + + // OpenACC 3.3, section 2.16: + // the term 'async-argument' means a nonnegative scalar integer expression, or + // one of the special values 'acc_async_noval' or 'acc_async_sync', as defined + // in the C header file and the Fortran opacc module. + // + // We are parsing this simply as list of assignment expressions (to avoid + // comma being troublesome), and will ensure it is an integral type. The + // 'special' types are defined as macros, so we can't really check those + // (other than perhaps as values at one point?), but the standard does say it + // is implementation-defined to use any other negative value. + // + // + bool FirstArg = true; + while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) { + if (!FirstArg) { + if (ExpectAndConsume(tok::comma)) + return true; + } + FirstArg = false; + + ExprResult CurArg = + getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + + if (CurArg.isInvalid()) + return true; + } + + return false; +} + ExprResult Parser::ParseOpenACCIDExpression() { ExprResult Res; if (getLangOpts().CPlusPlus) { @@ -399,6 +481,13 @@ void Parser::ParseOpenACCDirective() { // so we can always consume the close. T.consumeClose(); break; + case OpenACCDirectiveKind::Wait: + // OpenACC has an optional paren-wrapped 'wait-argument'. + if (ParseOpenACCWaitArgument()) + T.skipToEnd(); + else + T.consumeClose(); + break; } } else if (DirKind == OpenACCDirectiveKind::Cache) { // Cache's paren var-list is required, so error here if it isn't provided. diff --git a/clang/test/ParserOpenACC/parse-wait-construct.c b/clang/test/ParserOpenACC/parse-wait-construct.c new file mode 100644 index 00000000000000..9b210bc7094210 --- /dev/null +++ b/clang/test/ParserOpenACC/parse-wait-construct.c @@ -0,0 +1,157 @@ +// RUN: %clang_cc1 %s -verify -fopenacc + +void func() { + int i, j; + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait ( + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait () + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait () clause-list + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum:) + + // expected-error@+3{{expected expression}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum:) clause-list + + // 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 wait (devnum: i + j + + // expected-error@+2{{expected ':'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j) + + // expected-error@+3{{expected ':'}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues: + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues: + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues:) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (devnum: i + j:queues:) clause-list + + // expected-error@+4{{use of undeclared identifier 'devnum'}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j + + // expected-error@+2{{use of undeclared identifier 'devnum'}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j) + + // expected-error@+3{{use of undeclared identifier 'devnum'}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait (queues:devnum: i + j) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3 + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(i, j, 1+1, 3.3) clause-list + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(, + + // expected-error@+2{{expected expression}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(,) + + // expected-error@+3{{expected expression}} + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(,) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3 + + // expected-error@+4{{expected expression}} + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3, + + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3) + + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(queues:i, j, 1+1, 3.3) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3 + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:i, j, 1+1, 3.3) clause-list + + // expected-error@+3{{expected ')'}} + // expected-note@+2{{to match this '('}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3 + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) + // expected-warning@+2{{OpenACC clause parsing not yet implemented}} + // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}} + #pragma acc wait(devnum:3:queues:i, j, 1+1, 3.3) clause-list +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits