[clang] [OpenACC] Implement 'default' clause parsing. (PR #77002)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 4 12:51:20 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/77002.diff
4 Files Affected:
- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+2)
- (modified) clang/include/clang/Basic/OpenACCKinds.h (+12)
- (modified) clang/lib/Parse/ParseOpenACC.cpp (+70-5)
- (modified) clang/test/ParserOpenACC/parse-clauses.c (+96)
``````````diff
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 at +1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc loop seq,
+}
+
+void DefaultClause() {
+ // expected-error at +2{{expected '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial loop default
+ for(;;){}
+
+ // expected-error at +2{{expected '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default seq
+ for(;;){}
+
+ // expected-error at +2{{expected '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default, seq
+ for(;;){}
+
+ // expected-error at +4{{expected identifier}}
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(
+ for(;;){}
+
+ // expected-error at +4{{invalid value for 'default' clause; expected 'present' or 'none'}}
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default( seq
+ for(;;){}
+
+ // expected-error at +4{{expected identifier}}
+ // expected-error at +3{{expected ')'}}
+ // expected-note at +2{{to match this '('}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(, seq
+ for(;;){}
+
+ // expected-error at +3{{expected '('}}
+ // expected-error at +2{{expected identifier}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default)
+ for(;;){}
+
+ // expected-error at +3{{expected '('}}
+ // expected-error at +2{{expected identifier}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default) seq
+ for(;;){}
+
+ // expected-error at +3{{expected '('}}
+ // expected-error at +2{{expected identifier}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default), seq
+ for(;;){}
+
+ // expected-error at +2{{expected identifier}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default()
+ for(;;){}
+
+ // expected-error at +2{{expected identifier}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default() seq
+ for(;;){}
+
+ // expected-error at +2{{expected identifier}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(), seq
+ for(;;){}
+
+ // expected-error at +2{{invalid value for 'default' clause; expected 'present' or 'none'}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(invalid)
+ for(;;){}
+
+ // expected-error at +2{{invalid value for 'default' clause; expected 'present' or 'none'}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(auto) seq
+ for(;;){}
+
+ // expected-error at +2{{invalid value for 'default' clause; expected 'present' or 'none'}}
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(invalid), seq
+ for(;;){}
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(none)
+ for(;;){}
+
+ // expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc serial default(present), seq
+ for(;;){}
+
+
}
// expected-warning at +1{{OpenACC directives not yet implemented, pragma ignored}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/77002
More information about the cfe-commits
mailing list