@@ -21,24 +21,45 @@ using namespace clang;
21
21
using namespace llvm ;
22
22
23
23
namespace {
24
-
25
- // / This doesn't completely comprehend 'Compound Constructs' (as it just
26
- // / identifies the first token) just the first token of each. So
27
- // / this should only be used by `ParseOpenACCDirectiveKind`.
28
- OpenACCDirectiveKind getOpenACCDirectiveKind (StringRef Name) {
29
- return llvm::StringSwitch<OpenACCDirectiveKind>(Name)
30
- .Case (" parallel" , OpenACCDirectiveKind::Parallel)
31
- .Case (" serial" , OpenACCDirectiveKind::Serial)
32
- .Case (" kernels" , OpenACCDirectiveKind::Kernels)
33
- .Case (" data" , OpenACCDirectiveKind::Data)
34
- .Case (" host_data" , OpenACCDirectiveKind::HostData)
35
- .Case (" loop" , OpenACCDirectiveKind::Loop)
36
- .Case (" declare" , OpenACCDirectiveKind::Declare)
37
- .Case (" init" , OpenACCDirectiveKind::Init)
38
- .Case (" shutdown" , OpenACCDirectiveKind::Shutdown)
39
- .Case (" set" , OpenACCDirectiveKind::Shutdown)
40
- .Case (" update" , OpenACCDirectiveKind::Update)
41
- .Default (OpenACCDirectiveKind::Invalid);
24
+ // An enum that contains the extended 'partial' parsed variants. This type
25
+ // should never escape the initial parse functionality, but is useful for
26
+ // simplifying the implementation.
27
+ enum class OpenACCDirectiveKindEx {
28
+ Invalid = static_cast <int >(OpenACCDirectiveKind::Invalid),
29
+ // 'enter data' and 'exit data'
30
+ Enter,
31
+ Exit,
32
+ // FIXME: Atomic Variants
33
+ };
34
+
35
+ // Translate single-token string representations to the OpenACC Directive Kind.
36
+ // This doesn't completely comprehend 'Compound Constructs' (as it just
37
+ // identifies the first token), and doesn't fully handle 'enter data', 'exit
38
+ // data', nor any of the 'atomic' variants, just the first token of each. So
39
+ // this should only be used by `ParseOpenACCDirectiveKind`.
40
+ OpenACCDirectiveKindEx getOpenACCDirectiveKind (StringRef Name) {
41
+ OpenACCDirectiveKind DirKind =
42
+ llvm::StringSwitch<OpenACCDirectiveKind>(Name)
43
+ .Case (" parallel" , OpenACCDirectiveKind::Parallel)
44
+ .Case (" serial" , OpenACCDirectiveKind::Serial)
45
+ .Case (" kernels" , OpenACCDirectiveKind::Kernels)
46
+ .Case (" data" , OpenACCDirectiveKind::Data)
47
+ .Case (" host_data" , OpenACCDirectiveKind::HostData)
48
+ .Case (" loop" , OpenACCDirectiveKind::Loop)
49
+ .Case (" declare" , OpenACCDirectiveKind::Declare)
50
+ .Case (" init" , OpenACCDirectiveKind::Init)
51
+ .Case (" shutdown" , OpenACCDirectiveKind::Shutdown)
52
+ .Case (" set" , OpenACCDirectiveKind::Shutdown)
53
+ .Case (" update" , OpenACCDirectiveKind::Update)
54
+ .Default (OpenACCDirectiveKind::Invalid);
55
+
56
+ if (DirKind != OpenACCDirectiveKind::Invalid)
57
+ return static_cast <OpenACCDirectiveKindEx>(DirKind);
58
+
59
+ return llvm::StringSwitch<OpenACCDirectiveKindEx>(Name)
60
+ .Case (" enter" , OpenACCDirectiveKindEx::Enter)
61
+ .Case (" exit" , OpenACCDirectiveKindEx::Exit)
62
+ .Default (OpenACCDirectiveKindEx::Invalid);
42
63
}
43
64
44
65
bool isOpenACCDirectiveKind (OpenACCDirectiveKind Kind, StringRef Tok) {
@@ -59,6 +80,8 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) {
59
80
case OpenACCDirectiveKind::ParallelLoop:
60
81
case OpenACCDirectiveKind::SerialLoop:
61
82
case OpenACCDirectiveKind::KernelsLoop:
83
+ case OpenACCDirectiveKind::EnterData:
84
+ case OpenACCDirectiveKind::ExitData:
62
85
return false ;
63
86
64
87
case OpenACCDirectiveKind::Declare:
@@ -77,6 +100,32 @@ bool isOpenACCDirectiveKind(OpenACCDirectiveKind Kind, StringRef Tok) {
77
100
llvm_unreachable (" Unknown 'Kind' Passed" );
78
101
}
79
102
103
+ OpenACCDirectiveKind
104
+ ParseOpenACCEnterExitDataDirective (Parser &P, Token FirstTok,
105
+ StringRef FirstTokSpelling,
106
+ OpenACCDirectiveKindEx ExtDirKind) {
107
+ Token SecondTok = P.getCurToken ();
108
+
109
+ if (SecondTok.isAnnotation ()) {
110
+ P.Diag (FirstTok, diag::err_acc_invalid_directive) << 0 << FirstTokSpelling;
111
+ return OpenACCDirectiveKind::Invalid;
112
+ }
113
+
114
+ std::string SecondTokSpelling = P.getPreprocessor ().getSpelling (SecondTok);
115
+
116
+ if (!isOpenACCDirectiveKind (OpenACCDirectiveKind::Data, SecondTokSpelling)) {
117
+ P.Diag (FirstTok, diag::err_acc_invalid_directive)
118
+ << 1 << FirstTokSpelling << SecondTokSpelling;
119
+ return OpenACCDirectiveKind::Invalid;
120
+ }
121
+
122
+ P.ConsumeToken ();
123
+
124
+ return ExtDirKind == OpenACCDirectiveKindEx::Enter
125
+ ? OpenACCDirectiveKind::EnterData
126
+ : OpenACCDirectiveKind::ExitData;
127
+ }
128
+
80
129
// Parse and consume the tokens for OpenACC Directive/Construct kinds.
81
130
OpenACCDirectiveKind ParseOpenACCDirectiveKind (Parser &P) {
82
131
Token FirstTok = P.getCurToken ();
@@ -91,10 +140,28 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
91
140
P.ConsumeToken ();
92
141
std::string FirstTokSpelling = P.getPreprocessor ().getSpelling (FirstTok);
93
142
94
- OpenACCDirectiveKind DirKind = getOpenACCDirectiveKind (FirstTokSpelling);
143
+ OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind (FirstTokSpelling);
144
+
145
+ // OpenACCDirectiveKindEx is meant to be an extended list
146
+ // over OpenACCDirectiveKind, so any value below Invalid is one of the
147
+ // OpenACCDirectiveKind values. This switch takes care of all of the extra
148
+ // parsing required for the Extended values. At the end of this block,
149
+ // ExDirKind can be assumed to be a valid OpenACCDirectiveKind, so we can
150
+ // immediately cast it and use it as that.
151
+ if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) {
152
+ switch (ExDirKind) {
153
+ case OpenACCDirectiveKindEx::Invalid:
154
+ P.Diag (FirstTok, diag::err_acc_invalid_directive)
155
+ << 0 << FirstTokSpelling;
156
+ return OpenACCDirectiveKind::Invalid;
157
+ case OpenACCDirectiveKindEx::Enter:
158
+ case OpenACCDirectiveKindEx::Exit:
159
+ return ParseOpenACCEnterExitDataDirective (P, FirstTok, FirstTokSpelling,
160
+ ExDirKind);
161
+ }
162
+ }
95
163
96
- if (DirKind == OpenACCDirectiveKind::Invalid)
97
- P.Diag (FirstTok, diag::err_acc_invalid_directive) << FirstTokSpelling;
164
+ OpenACCDirectiveKind DirKind = static_cast <OpenACCDirectiveKind>(ExDirKind);
98
165
99
166
// Combined Constructs allows parallel loop, serial loop, or kernels loop. Any
100
167
// other attempt at a combined construct will be diagnosed as an invalid
0 commit comments