aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
authorErich Keane <ekeane@nvidia.com>2023-11-17 10:47:42 -0800
committerGitHub <noreply@github.com>2023-11-17 10:47:42 -0800
commit64b6ef02e263a8ee48bd91f8b06dd3945eb9be44 (patch)
treedcf4aa009b9ac9a001cb7ce7127983fb1cde5bd3 /clang
parent704c22473641e26d95435c55aa482fbf5abbbc2c (diff)
downloadllvm-64b6ef02e263a8ee48bd91f8b06dd3945eb9be44.zip
llvm-64b6ef02e263a8ee48bd91f8b06dd3945eb9be44.tar.gz
llvm-64b6ef02e263a8ee48bd91f8b06dd3945eb9be44.tar.bz2
[OpenACC] Implement initial parsing for `parallel` construct (#72661)
As the first real parsing effort for the OpenACC implementation effort, this implements the parsing for first construct/directive name. This does not do any semantic analysis, nor any of the clauses. Those will come in a future patch. For the time being, we warn when we hit a point that we don't implement the parsing for either of these situations.
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td15
-rw-r--r--clang/include/clang/Basic/OpenACCKinds.h30
-rw-r--r--clang/include/clang/Parse/Parser.h4
-rw-r--r--clang/include/clang/Parse/RAIIObjectsForParser.h19
-rw-r--r--clang/lib/Parse/ParseOpenACC.cpp69
-rw-r--r--clang/lib/Parse/Parser.cpp5
-rw-r--r--clang/test/ParserOpenACC/parse-constructs.c16
-rw-r--r--clang/test/ParserOpenACC/unimplemented.c6
-rw-r--r--clang/test/ParserOpenACC/unimplemented.cpp6
9 files changed, 160 insertions, 10 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index c3d0605..1beddb5 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1343,13 +1343,20 @@ def err_openclcxx_virtual_function : Error<
"virtual functions are not supported in C++ for OpenCL">;
// OpenACC Support.
-def warn_pragma_acc_ignored : Warning<
- "unexpected '#pragma acc ...' in program">, InGroup<SourceUsesOpenACC>, DefaultIgnore;
-def err_acc_unexpected_directive : Error<
- "unexpected OpenACC directive %select{|'#pragma acc %1'}0">;
+def warn_pragma_acc_ignored
+ : Warning<"unexpected '#pragma acc ...' in program">,
+ InGroup<SourceUsesOpenACC>,
+ DefaultIgnore;
+def err_acc_unexpected_directive
+ : Error<"unexpected OpenACC directive %select{|'#pragma acc %1'}0">;
def warn_pragma_acc_unimplemented
: Warning<"OpenACC directives not yet implemented, pragma ignored">,
InGroup<SourceUsesOpenACC>;
+def warn_pragma_acc_unimplemented_clause_parsing
+ : Warning<"OpenACC clause parsing not yet implemented">,
+ InGroup<SourceUsesOpenACC>;
+def err_acc_invalid_directive
+ : Error<"invalid OpenACC directive '%0'">;
// OpenMP support.
def warn_pragma_omp_ignored : Warning<
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
new file mode 100644
index 0000000..79780b7
--- /dev/null
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -0,0 +1,30 @@
+//===--- OpenACCKinds.h - OpenACC Enums -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Defines some OpenACC-specific enums and functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OPENACCKINDS_H
+#define LLVM_CLANG_BASIC_OPENACCKINDS_H
+
+namespace clang {
+// Represents the Construct/Directive kind of a pragma directive. Note the
+// OpenACC standard is inconsistent between calling these Construct vs
+// Directive, but we're calling it a Directive to be consistent with OpenMP.
+enum class OpenACCDirectiveKind {
+ // Compute Constructs.
+ Parallel,
+
+ // Invalid.
+ Invalid,
+};
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 2f56da8..d20a26d 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -53,6 +53,7 @@ namespace clang {
class Parser : public CodeCompletionHandler {
friend class ColonProtectionRAIIObject;
friend class ParsingOpenMPDirectiveRAII;
+ friend class ParsingOpenACCDirectiveRAII;
friend class InMessageExpressionRAIIObject;
friend class OffsetOfStateRAIIObject;
friend class PoisonSEHIdentifiersRAIIObject;
@@ -230,6 +231,9 @@ class Parser : public CodeCompletionHandler {
/// Parsing OpenMP directive mode.
bool OpenMPDirectiveParsing = false;
+ /// Parsing OpenACC directive mode.
+ bool OpenACCDirectiveParsing = false;
+
/// When true, we are directly inside an Objective-C message
/// send expression.
///
diff --git a/clang/include/clang/Parse/RAIIObjectsForParser.h b/clang/include/clang/Parse/RAIIObjectsForParser.h
index cb525c9..e1626a7 100644
--- a/clang/include/clang/Parse/RAIIObjectsForParser.h
+++ b/clang/include/clang/Parse/RAIIObjectsForParser.h
@@ -309,6 +309,25 @@ namespace clang {
~ParsingOpenMPDirectiveRAII() { restore(); }
};
+ /// Activates OpenACC parsing mode to preseve OpenACC specific annotation
+ /// tokens.
+ class ParsingOpenACCDirectiveRAII {
+ Parser &P;
+ bool OldVal;
+
+ public:
+ ParsingOpenACCDirectiveRAII(Parser &P, bool Value = true)
+ : P(P), OldVal(P.OpenACCDirectiveParsing) {
+ P.OpenACCDirectiveParsing = Value;
+ }
+
+ /// This can be used to restore the state early, before the dtor
+ /// is run.
+ void restore() { P.OpenMPDirectiveParsing = OldVal; }
+
+ ~ParsingOpenACCDirectiveRAII() { restore(); }
+ };
+
/// RAII object that makes '>' behave either as an operator
/// or as the closing angle bracket for a template argument list.
class GreaterThanIsOperatorScope {
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index ab79051..9f13aad 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -10,18 +10,79 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/OpenACCKinds.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
using namespace clang;
+using namespace llvm;
+namespace {
+
+// Translate single-token string representations to the OpenACC Directive Kind.
+OpenACCDirectiveKind GetOpenACCDirectiveKind(StringRef Name) {
+ return llvm::StringSwitch<OpenACCDirectiveKind>(Name)
+ .Case("parallel", OpenACCDirectiveKind::Parallel)
+ .Default(OpenACCDirectiveKind::Invalid);
+}
+
+// Parse and consume the tokens for OpenACC Directive/Construct kinds.
+OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
+ Token FirstTok = P.getCurToken();
+ P.ConsumeToken();
+ std::string FirstTokSpelling = P.getPreprocessor().getSpelling(FirstTok);
+
+ OpenACCDirectiveKind DirKind = GetOpenACCDirectiveKind(FirstTokSpelling);
+
+ if (DirKind == OpenACCDirectiveKind::Invalid)
+ P.Diag(FirstTok, diag::err_acc_invalid_directive) << FirstTokSpelling;
+
+ return DirKind;
+}
+
+void ParseOpenACCClauseList(Parser &P) {
+ // FIXME: In the future, we'll start parsing the clauses here, but for now we
+ // haven't implemented that, so just emit the unimplemented diagnostic and
+ // fail reasonably.
+ if (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
+ P.Diag(P.getCurToken(), diag::warn_pragma_acc_unimplemented_clause_parsing);
+}
+
+void ParseOpenACCDirective(Parser &P) {
+ ParseOpenACCDirectiveKind(P);
+
+ // Parses the list of clauses, if present.
+ ParseOpenACCClauseList(P);
+
+ P.Diag(P.getCurToken(), diag::warn_pragma_acc_unimplemented);
+ P.SkipUntil(tok::annot_pragma_openacc_end);
+}
+
+} // namespace
+
+// Parse OpenACC directive on a declaration.
Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() {
- Diag(Tok, diag::warn_pragma_acc_unimplemented);
- SkipUntil(tok::annot_pragma_openacc_end);
+ assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
+
+ ParsingOpenACCDirectiveRAII DirScope(*this);
+ ConsumeAnnotationToken();
+
+ ParseOpenACCDirective(*this);
+
return nullptr;
}
+
+// Parse OpenACC Directive on a Statement.
StmtResult Parser::ParseOpenACCDirectiveStmt() {
- Diag(Tok, diag::warn_pragma_acc_unimplemented);
- SkipUntil(tok::annot_pragma_openacc_end);
+ assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
+
+ ParsingOpenACCDirectiveRAII DirScope(*this);
+ ConsumeAnnotationToken();
+
+ ParseOpenACCDirective(*this);
+
return StmtEmpty();
}
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 9eed088..1baeb2a 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -320,8 +320,9 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
break;
case tok::annot_pragma_openacc:
case tok::annot_pragma_openacc_end:
- // FIXME: Like OpenMP above, we should not be doing this if we're parsing
- // an OpenACC Directive.
+ // Stop before an OpenACC pragma boundary.
+ if (OpenACCDirectiveParsing)
+ return false;
ConsumeAnnotationToken();
break;
case tok::annot_module_begin:
diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c
new file mode 100644
index 0000000..4c2188cc
--- /dev/null
+++ b/clang/test/ParserOpenACC/parse-constructs.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -verify -fopenacc
+
+void func() {
+ // expected-error@+2{{invalid OpenACC directive 'invalid'}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc invalid
+ for(;;){}
+
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc parallel clause list
+ for(;;){}
+ // expected-warning@+2{{OpenACC clause parsing not yet implemented}}
+ // expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
+#pragma acc parallel() clause list
+}
diff --git a/clang/test/ParserOpenACC/unimplemented.c b/clang/test/ParserOpenACC/unimplemented.c
index c1228c8..dd2e8be 100644
--- a/clang/test/ParserOpenACC/unimplemented.c
+++ b/clang/test/ParserOpenACC/unimplemented.c
@@ -1,12 +1,16 @@
// RUN: %clang_cc1 %s -verify -fopenacc
// Parser::ParseExternalDeclaration
+// expected-error@+3{{invalid OpenACC directive 'not'}}
+// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc not yet implemented
int foo;
struct S {
// Parser::ParseStructUnionBody
+// expected-error@+3{{invalid OpenACC directive 'not'}}
+// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc not yet implemented
int foo;
@@ -14,6 +18,8 @@ struct S {
void func() {
// Parser::ParseStmtOrDeclarationAfterAttributes
+// expected-error@+3{{invalid OpenACC directive 'not'}}
+// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc not yet implemented
while(0) {}
diff --git a/clang/test/ParserOpenACC/unimplemented.cpp b/clang/test/ParserOpenACC/unimplemented.cpp
index 095cbf5..4f6c5a6 100644
--- a/clang/test/ParserOpenACC/unimplemented.cpp
+++ b/clang/test/ParserOpenACC/unimplemented.cpp
@@ -1,12 +1,16 @@
// RUN: %clang_cc1 %s -verify -fopenacc
// Parser::ParseExternalDeclaration
+// expected-error@+3{{invalid OpenACC directive 'not'}}
+// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc not yet implemented
int foo;
struct S {
// Parser::ParseCXXClassMemberDeclarationWithPragmas
+// expected-error@+3{{invalid OpenACC directive 'not'}}
+// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc not yet implemented
int foo;
@@ -14,6 +18,8 @@ struct S {
void func() {
// Parser::ParseStmtOrDeclarationAfterAttributes
+// expected-error@+3{{invalid OpenACC directive 'not'}}
+// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
#pragma acc not yet implemented
while(false) {}