-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[OpenACC] Implement 'default' clause parsing. #77002
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
Conversation
A simple clause that is permitted on a few different constructs, 'default' takes a required parameter of either 'none' or 'present'. This patch implements parsing for it.
@llvm/pr-subscribers-clang Author: Erich Keane (erichkeane) ChangesA simple clause that is permitted on a few different constructs, Full diff: https://github.com/llvm/llvm-project/pull/77002.diff 4 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index e4b1069cde1850..088f8b74983c86 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1364,6 +1364,8 @@ def err_acc_invalid_clause : Error<"invalid OpenACC clause %0">;
def err_acc_missing_directive : Error<"expected OpenACC directive">;
def err_acc_invalid_open_paren
: Error<"expected clause-list or newline in OpenACC directive">;
+def err_acc_invalid_default_clause_kind
+ : Error<"invalid value for 'default' clause; expected 'present' or 'none'">;
// OpenMP support.
def warn_pragma_omp_ignored : Warning<
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index 3117d584d347b9..e507afe46a6540 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -90,9 +90,21 @@ enum class OpenACCClauseKind {
Vector,
// 'nohost' clause, allowed on 'routine' directives.
NoHost,
+ // 'default' clause, allowed on parallel, serial, kernel (and compound)
+ // constructs.
+ Default,
// Represents an invalid clause, for the purposes of parsing.
Invalid,
};
+
+enum class OpenACCDefaultClauseKind {
+ // 'none' option.
+ None,
+ // 'present' option.
+ Present,
+ // Not a valid option.
+ Invalid,
+};
} // namespace clang
#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 67325f0a286a99..27e6c29b546485 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -76,12 +76,17 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
if (Tok.is(tok::kw_auto))
return OpenACCClauseKind::Auto;
+ // default is a keyword, so make sure we parse it correctly.
+ if (Tok.is(tok::kw_default))
+ return OpenACCClauseKind::Default;
+
if (!Tok.is(tok::identifier))
return OpenACCClauseKind::Invalid;
return llvm::StringSwitch<OpenACCClauseKind>(
Tok.getIdentifierInfo()->getName())
.Case("auto", OpenACCClauseKind::Auto)
+ .Case("default", OpenACCClauseKind::Default)
.Case("finalize", OpenACCClauseKind::Finalize)
.Case("if_present", OpenACCClauseKind::IfPresent)
.Case("independent", OpenACCClauseKind::Independent)
@@ -106,6 +111,17 @@ OpenACCAtomicKind getOpenACCAtomicKind(Token Tok) {
.Default(OpenACCAtomicKind::Invalid);
}
+OpenACCDefaultClauseKind getOpenACCDefaultClauseKind(Token Tok) {
+ if (!Tok.is(tok::identifier))
+ return OpenACCDefaultClauseKind::Invalid;
+
+ return llvm::StringSwitch<OpenACCDefaultClauseKind>(
+ Tok.getIdentifierInfo()->getName())
+ .Case("none", OpenACCDefaultClauseKind::None)
+ .Case("present", OpenACCDefaultClauseKind::Present)
+ .Default(OpenACCDefaultClauseKind::Invalid);
+}
+
enum class OpenACCSpecialTokenKind {
ReadOnly,
DevNum,
@@ -291,13 +307,63 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
return DirKind;
}
+bool ClauseHasRequiredParens(OpenACCClauseKind Kind) {
+ return Kind == OpenACCClauseKind::Default;
+}
+
+bool ParseOpenACCClauseParams(Parser &P, OpenACCClauseKind Kind) {
+ BalancedDelimiterTracker Parens(P, tok::l_paren,
+ tok::annot_pragma_openacc_end);
+
+ if (ClauseHasRequiredParens(Kind)) {
+ if (Parens.expectAndConsume()) {
+ // We are missing a paren, so assume that the person just forgot the
+ // parameter. Return 'false' so we try to continue on and parse the next
+ // clause.
+ P.SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
+ Parser::StopBeforeMatch);
+ return false;
+ }
+
+ switch (Kind) {
+ case OpenACCClauseKind::Default: {
+ Token DefKindTok = P.getCurToken();
+ // 'default' accepts 'present' or 'none'. Be a little liberal here to
+ // allow things like 'auto' or 'default'.
+ // TODO ERICH: Make 'keyword like tokens' via tok::getKeywordSpelling'
+ // or 'getIdentifierInfo' isKeyword
+ if (!DefKindTok.is(tok::identifier) &&
+ (DefKindTok.isAnnotation() || !DefKindTok.getIdentifierInfo() ||
+ !DefKindTok.getIdentifierInfo()->isKeyword(P.getLangOpts()))) {
+ P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
+ break;
+ }
+
+ P.ConsumeToken();
+
+ if (getOpenACCDefaultClauseKind(DefKindTok) ==
+ OpenACCDefaultClauseKind::Invalid)
+ P.Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
+
+ break;
+ }
+ default:
+ llvm_unreachable("Not a required parens type?");
+ }
+
+ return Parens.consumeClose();
+ }
+ // FIXME: Handle optional parens
+ 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.
-// However, they all are named with a single-identifier (or auto!) token,
-// followed in some cases by either braces or parens.
+// However, they all are named with a single-identifier (or auto/default!)
+// token, followed in some cases by either braces or parens.
bool ParseOpenACCClause(Parser &P) {
- if (!P.getCurToken().isOneOf(tok::identifier, tok::kw_auto))
+ if (!P.getCurToken().isOneOf(tok::identifier, tok::kw_auto, tok::kw_default))
return P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken());
@@ -309,8 +375,7 @@ bool ParseOpenACCClause(Parser &P) {
// Consume the clause name.
P.ConsumeToken();
- // FIXME: For future clauses, we need to handle parens/etc below.
- return false;
+ return ParseOpenACCClauseParams(P, Kind);
}
// Skip until we see the end of pragma token, but don't consume it. This is us
diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index 1e05d82906aedc..aedf0c711ad15b 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -54,6 +54,102 @@ void func() {
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc loop seq,
+}
+
+void DefaultClause() {
+ // expected-error@+2{{expected '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial loop default
+ for(;;){}
+
+ // expected-error@+2{{expected '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default seq
+ for(;;){}
+
+ // expected-error@+2{{expected '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default, seq
+ for(;;){}
+
+ // 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 serial default(
+ for(;;){}
+
+ // expected-error@+4{{invalid value for 'default' clause; expected 'present' or 'none'}}
+ // expected-error@+3{{expected ')'}}
+ // expected-note@+2{{to match this '('}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default( seq
+ for(;;){}
+
+ // 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 serial default(, seq
+ for(;;){}
+
+ // expected-error@+3{{expected '('}}
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default)
+ for(;;){}
+
+ // expected-error@+3{{expected '('}}
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default) seq
+ for(;;){}
+
+ // expected-error@+3{{expected '('}}
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default), seq
+ for(;;){}
+
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default()
+ for(;;){}
+
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default() seq
+ for(;;){}
+
+ // expected-error@+2{{expected identifier}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(), seq
+ for(;;){}
+
+ // expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(invalid)
+ for(;;){}
+
+ // expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(auto) seq
+ for(;;){}
+
+ // expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(invalid), seq
+ for(;;){}
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(none)
+ for(;;){}
+
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(present), seq
+ for(;;){}
+
+
}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
A simple clause that is permitted on a few different constructs, 'default' takes a required parameter of either 'none' or 'present'. This patch implements parsing for it.
A simple clause that is permitted on a few different constructs,
'default' takes a required parameter of either 'none' or 'present'.
This patch implements parsing for it.