Skip to content

[OpenACC] Implement 'wait' construct parsing #74752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/OpenACCKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ enum class OpenACCDirectiveKind {
Shutdown,
Set,
Update,
// FIXME: wait construct.
Wait,

// Procedure Calls in Compute Regions.
Routine,
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
//===--------------------------------------------------------------------===//
Expand Down
89 changes: 89 additions & 0 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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.
Expand Down
157 changes: 157 additions & 0 deletions clang/test/ParserOpenACC/parse-wait-construct.c
Original file line number Diff line number Diff line change
@@ -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
}