Skip to content

Commit 64b6ef0

Browse files
authored
[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.
1 parent 704c224 commit 64b6ef0

File tree

9 files changed

+160
-10
lines changed

9 files changed

+160
-10
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,13 +1343,20 @@ def err_openclcxx_virtual_function : Error<
13431343
"virtual functions are not supported in C++ for OpenCL">;
13441344

13451345
// OpenACC Support.
1346-
def warn_pragma_acc_ignored : Warning<
1347-
"unexpected '#pragma acc ...' in program">, InGroup<SourceUsesOpenACC>, DefaultIgnore;
1348-
def err_acc_unexpected_directive : Error<
1349-
"unexpected OpenACC directive %select{|'#pragma acc %1'}0">;
1346+
def warn_pragma_acc_ignored
1347+
: Warning<"unexpected '#pragma acc ...' in program">,
1348+
InGroup<SourceUsesOpenACC>,
1349+
DefaultIgnore;
1350+
def err_acc_unexpected_directive
1351+
: Error<"unexpected OpenACC directive %select{|'#pragma acc %1'}0">;
13501352
def warn_pragma_acc_unimplemented
13511353
: Warning<"OpenACC directives not yet implemented, pragma ignored">,
13521354
InGroup<SourceUsesOpenACC>;
1355+
def warn_pragma_acc_unimplemented_clause_parsing
1356+
: Warning<"OpenACC clause parsing not yet implemented">,
1357+
InGroup<SourceUsesOpenACC>;
1358+
def err_acc_invalid_directive
1359+
: Error<"invalid OpenACC directive '%0'">;
13531360

13541361
// OpenMP support.
13551362
def warn_pragma_omp_ignored : Warning<
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===--- OpenACCKinds.h - OpenACC Enums -------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// \file
10+
/// Defines some OpenACC-specific enums and functions.
11+
///
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CLANG_BASIC_OPENACCKINDS_H
15+
#define LLVM_CLANG_BASIC_OPENACCKINDS_H
16+
17+
namespace clang {
18+
// Represents the Construct/Directive kind of a pragma directive. Note the
19+
// OpenACC standard is inconsistent between calling these Construct vs
20+
// Directive, but we're calling it a Directive to be consistent with OpenMP.
21+
enum class OpenACCDirectiveKind {
22+
// Compute Constructs.
23+
Parallel,
24+
25+
// Invalid.
26+
Invalid,
27+
};
28+
} // namespace clang
29+
30+
#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H

clang/include/clang/Parse/Parser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ namespace clang {
5353
class Parser : public CodeCompletionHandler {
5454
friend class ColonProtectionRAIIObject;
5555
friend class ParsingOpenMPDirectiveRAII;
56+
friend class ParsingOpenACCDirectiveRAII;
5657
friend class InMessageExpressionRAIIObject;
5758
friend class OffsetOfStateRAIIObject;
5859
friend class PoisonSEHIdentifiersRAIIObject;
@@ -230,6 +231,9 @@ class Parser : public CodeCompletionHandler {
230231
/// Parsing OpenMP directive mode.
231232
bool OpenMPDirectiveParsing = false;
232233

234+
/// Parsing OpenACC directive mode.
235+
bool OpenACCDirectiveParsing = false;
236+
233237
/// When true, we are directly inside an Objective-C message
234238
/// send expression.
235239
///

clang/include/clang/Parse/RAIIObjectsForParser.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,25 @@ namespace clang {
309309
~ParsingOpenMPDirectiveRAII() { restore(); }
310310
};
311311

312+
/// Activates OpenACC parsing mode to preseve OpenACC specific annotation
313+
/// tokens.
314+
class ParsingOpenACCDirectiveRAII {
315+
Parser &P;
316+
bool OldVal;
317+
318+
public:
319+
ParsingOpenACCDirectiveRAII(Parser &P, bool Value = true)
320+
: P(P), OldVal(P.OpenACCDirectiveParsing) {
321+
P.OpenACCDirectiveParsing = Value;
322+
}
323+
324+
/// This can be used to restore the state early, before the dtor
325+
/// is run.
326+
void restore() { P.OpenMPDirectiveParsing = OldVal; }
327+
328+
~ParsingOpenACCDirectiveRAII() { restore(); }
329+
};
330+
312331
/// RAII object that makes '>' behave either as an operator
313332
/// or as the closing angle bracket for a template argument list.
314333
class GreaterThanIsOperatorScope {

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,79 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "clang/Basic/OpenACCKinds.h"
1314
#include "clang/Parse/ParseDiagnostic.h"
1415
#include "clang/Parse/Parser.h"
16+
#include "clang/Parse/RAIIObjectsForParser.h"
17+
#include "llvm/ADT/StringRef.h"
18+
#include "llvm/ADT/StringSwitch.h"
1519

1620
using namespace clang;
21+
using namespace llvm;
1722

23+
namespace {
24+
25+
// Translate single-token string representations to the OpenACC Directive Kind.
26+
OpenACCDirectiveKind GetOpenACCDirectiveKind(StringRef Name) {
27+
return llvm::StringSwitch<OpenACCDirectiveKind>(Name)
28+
.Case("parallel", OpenACCDirectiveKind::Parallel)
29+
.Default(OpenACCDirectiveKind::Invalid);
30+
}
31+
32+
// Parse and consume the tokens for OpenACC Directive/Construct kinds.
33+
OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
34+
Token FirstTok = P.getCurToken();
35+
P.ConsumeToken();
36+
std::string FirstTokSpelling = P.getPreprocessor().getSpelling(FirstTok);
37+
38+
OpenACCDirectiveKind DirKind = GetOpenACCDirectiveKind(FirstTokSpelling);
39+
40+
if (DirKind == OpenACCDirectiveKind::Invalid)
41+
P.Diag(FirstTok, diag::err_acc_invalid_directive) << FirstTokSpelling;
42+
43+
return DirKind;
44+
}
45+
46+
void ParseOpenACCClauseList(Parser &P) {
47+
// FIXME: In the future, we'll start parsing the clauses here, but for now we
48+
// haven't implemented that, so just emit the unimplemented diagnostic and
49+
// fail reasonably.
50+
if (P.getCurToken().isNot(tok::annot_pragma_openacc_end))
51+
P.Diag(P.getCurToken(), diag::warn_pragma_acc_unimplemented_clause_parsing);
52+
}
53+
54+
void ParseOpenACCDirective(Parser &P) {
55+
ParseOpenACCDirectiveKind(P);
56+
57+
// Parses the list of clauses, if present.
58+
ParseOpenACCClauseList(P);
59+
60+
P.Diag(P.getCurToken(), diag::warn_pragma_acc_unimplemented);
61+
P.SkipUntil(tok::annot_pragma_openacc_end);
62+
}
63+
64+
} // namespace
65+
66+
// Parse OpenACC directive on a declaration.
1867
Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() {
19-
Diag(Tok, diag::warn_pragma_acc_unimplemented);
20-
SkipUntil(tok::annot_pragma_openacc_end);
68+
assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
69+
70+
ParsingOpenACCDirectiveRAII DirScope(*this);
71+
ConsumeAnnotationToken();
72+
73+
ParseOpenACCDirective(*this);
74+
2175
return nullptr;
2276
}
77+
78+
// Parse OpenACC Directive on a Statement.
2379
StmtResult Parser::ParseOpenACCDirectiveStmt() {
24-
Diag(Tok, diag::warn_pragma_acc_unimplemented);
25-
SkipUntil(tok::annot_pragma_openacc_end);
80+
assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
81+
82+
ParsingOpenACCDirectiveRAII DirScope(*this);
83+
ConsumeAnnotationToken();
84+
85+
ParseOpenACCDirective(*this);
86+
2687
return StmtEmpty();
2788
}

clang/lib/Parse/Parser.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,9 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
320320
break;
321321
case tok::annot_pragma_openacc:
322322
case tok::annot_pragma_openacc_end:
323-
// FIXME: Like OpenMP above, we should not be doing this if we're parsing
324-
// an OpenACC Directive.
323+
// Stop before an OpenACC pragma boundary.
324+
if (OpenACCDirectiveParsing)
325+
return false;
325326
ConsumeAnnotationToken();
326327
break;
327328
case tok::annot_module_begin:
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_cc1 %s -verify -fopenacc
2+
3+
void func() {
4+
// expected-error@+2{{invalid OpenACC directive 'invalid'}}
5+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
6+
#pragma acc invalid
7+
for(;;){}
8+
9+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
10+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
11+
#pragma acc parallel clause list
12+
for(;;){}
13+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
14+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
15+
#pragma acc parallel() clause list
16+
}

clang/test/ParserOpenACC/unimplemented.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
// RUN: %clang_cc1 %s -verify -fopenacc
22

33
// Parser::ParseExternalDeclaration
4+
// expected-error@+3{{invalid OpenACC directive 'not'}}
5+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
46
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
57
#pragma acc not yet implemented
68
int foo;
79

810
struct S {
911
// Parser::ParseStructUnionBody
12+
// expected-error@+3{{invalid OpenACC directive 'not'}}
13+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
1014
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
1115
#pragma acc not yet implemented
1216
int foo;
1317
};
1418

1519
void func() {
1620
// Parser::ParseStmtOrDeclarationAfterAttributes
21+
// expected-error@+3{{invalid OpenACC directive 'not'}}
22+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
1723
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
1824
#pragma acc not yet implemented
1925
while(0) {}

clang/test/ParserOpenACC/unimplemented.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
// RUN: %clang_cc1 %s -verify -fopenacc
22

33
// Parser::ParseExternalDeclaration
4+
// expected-error@+3{{invalid OpenACC directive 'not'}}
5+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
46
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
57
#pragma acc not yet implemented
68
int foo;
79

810
struct S {
911
// Parser::ParseCXXClassMemberDeclarationWithPragmas
12+
// expected-error@+3{{invalid OpenACC directive 'not'}}
13+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
1014
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
1115
#pragma acc not yet implemented
1216
int foo;
1317
};
1418

1519
void func() {
1620
// Parser::ParseStmtOrDeclarationAfterAttributes
21+
// expected-error@+3{{invalid OpenACC directive 'not'}}
22+
// expected-warning@+2{{OpenACC clause parsing not yet implemented}}
1723
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
1824
#pragma acc not yet implemented
1925
while(false) {}

0 commit comments

Comments
 (0)