aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp129
1 files changed, 123 insertions, 6 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp b/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp
index 67325f0a286a..c9224d3ae910 100644
--- a/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp
+++ b/contrib/llvm-project/clang/lib/Parse/ParseOpenACC.cpp
@@ -76,16 +76,27 @@ 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 is also a keyword, make sure we parse it correctly.
+ if (Tok.is(tok::kw_if))
+ return OpenACCClauseKind::If;
+
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", OpenACCClauseKind::If)
.Case("if_present", OpenACCClauseKind::IfPresent)
.Case("independent", OpenACCClauseKind::Independent)
.Case("nohost", OpenACCClauseKind::NoHost)
+ .Case("self", OpenACCClauseKind::Self)
.Case("seq", OpenACCClauseKind::Seq)
.Case("vector", OpenACCClauseKind::Vector)
.Case("worker", OpenACCClauseKind::Worker)
@@ -106,6 +117,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,
@@ -176,6 +198,22 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, Token Tok) {
llvm_unreachable("Unknown 'Kind' Passed");
}
+/// Used for cases where we expect an identifier-like token, but don't want to
+/// give awkward error messages in cases where it is accidentially a keyword.
+bool expectIdentifierOrKeyword(Parser &P) {
+ Token Tok = P.getCurToken();
+
+ if (Tok.is(tok::identifier))
+ return false;
+
+ if (!Tok.isAnnotation() && Tok.getIdentifierInfo() &&
+ Tok.getIdentifierInfo()->isKeyword(P.getLangOpts()))
+ return false;
+
+ P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
+ return true;
+}
+
OpenACCDirectiveKind
ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,
OpenACCDirectiveKindEx ExtDirKind) {
@@ -291,14 +329,94 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
return DirKind;
}
+bool ClauseHasOptionalParens(OpenACCClauseKind Kind) {
+ return Kind == OpenACCClauseKind::Self;
+}
+
+bool ClauseHasRequiredParens(OpenACCClauseKind Kind) {
+ return Kind == OpenACCClauseKind::Default || Kind == OpenACCClauseKind::If;
+}
+
+ExprResult ParseOpenACCConditionalExpr(Parser &P) {
+ // FIXME: It isn't clear if the spec saying 'condition' means the same as
+ // it does in an if/while/etc (See ParseCXXCondition), however as it was
+ // written with Fortran/C in mind, we're going to assume it just means an
+ // 'expression evaluating to boolean'.
+ return P.getActions().CorrectDelayedTyposInExpr(P.ParseExpression());
+}
+
+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();
+
+ if (expectIdentifierOrKeyword(P))
+ break;
+
+ P.ConsumeToken();
+
+ if (getOpenACCDefaultClauseKind(DefKindTok) ==
+ OpenACCDefaultClauseKind::Invalid)
+ P.Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
+
+ break;
+ }
+ case OpenACCClauseKind::If: {
+ ExprResult CondExpr = ParseOpenACCConditionalExpr(P);
+ // An invalid expression can be just about anything, so just give up on
+ // this clause list.
+ if (CondExpr.isInvalid())
+ return true;
+ break;
+ }
+ default:
+ llvm_unreachable("Not a required parens type?");
+ }
+
+ return Parens.consumeClose();
+ } else if (ClauseHasOptionalParens(Kind)) {
+ if (!Parens.consumeOpen()) {
+ switch (Kind) {
+ case OpenACCClauseKind::Self: {
+ ExprResult CondExpr = ParseOpenACCConditionalExpr(P);
+ // An invalid expression can be just about anything, so just give up on
+ // this clause list.
+ if (CondExpr.isInvalid())
+ return true;
+ break;
+ }
+ default:
+ llvm_unreachable("Not an optional parens type?");
+ }
+ Parens.consumeClose();
+ }
+ }
+ 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))
- return P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
+ // A number of clause names are actually keywords, so accept a keyword that
+ // can be converted to a name.
+ if (expectIdentifierOrKeyword(P))
+ return true;
OpenACCClauseKind Kind = getOpenACCClauseKind(P.getCurToken());
@@ -309,8 +427,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