@@ -22,8 +22,10 @@ using namespace llvm;
22
22
23
23
namespace {
24
24
25
- // Translate single-token string representations to the OpenACC Directive Kind.
26
- OpenACCDirectiveKind GetOpenACCDirectiveKind (StringRef Name) {
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) {
27
29
return llvm::StringSwitch<OpenACCDirectiveKind>(Name)
28
30
.Case (" parallel" , OpenACCDirectiveKind::Parallel)
29
31
.Case (" serial" , OpenACCDirectiveKind::Serial)
@@ -39,6 +41,42 @@ OpenACCDirectiveKind GetOpenACCDirectiveKind(StringRef Name) {
39
41
.Default (OpenACCDirectiveKind::Invalid);
40
42
}
41
43
44
+ bool isOpenACCDirectiveKind (OpenACCDirectiveKind Kind, StringRef Tok) {
45
+ switch (Kind) {
46
+ case OpenACCDirectiveKind::Parallel:
47
+ return Tok == " parallel" ;
48
+ case OpenACCDirectiveKind::Serial:
49
+ return Tok == " serial" ;
50
+ case OpenACCDirectiveKind::Kernels:
51
+ return Tok == " kernels" ;
52
+ case OpenACCDirectiveKind::Data:
53
+ return Tok == " data" ;
54
+ case OpenACCDirectiveKind::HostData:
55
+ return Tok == " host_data" ;
56
+ case OpenACCDirectiveKind::Loop:
57
+ return Tok == " loop" ;
58
+
59
+ case OpenACCDirectiveKind::ParallelLoop:
60
+ case OpenACCDirectiveKind::SerialLoop:
61
+ case OpenACCDirectiveKind::KernelsLoop:
62
+ return false ;
63
+
64
+ case OpenACCDirectiveKind::Declare:
65
+ return Tok == " declare" ;
66
+ case OpenACCDirectiveKind::Init:
67
+ return Tok == " init" ;
68
+ case OpenACCDirectiveKind::Shutdown:
69
+ return Tok == " shutdown" ;
70
+ case OpenACCDirectiveKind::Set:
71
+ return Tok == " set" ;
72
+ case OpenACCDirectiveKind::Update:
73
+ return Tok == " update" ;
74
+ case OpenACCDirectiveKind::Invalid:
75
+ return false ;
76
+ }
77
+ llvm_unreachable (" Unknown 'Kind' Passed" );
78
+ }
79
+
42
80
// Parse and consume the tokens for OpenACC Directive/Construct kinds.
43
81
OpenACCDirectiveKind ParseOpenACCDirectiveKind (Parser &P) {
44
82
Token FirstTok = P.getCurToken ();
@@ -53,11 +91,35 @@ OpenACCDirectiveKind ParseOpenACCDirectiveKind(Parser &P) {
53
91
P.ConsumeToken ();
54
92
std::string FirstTokSpelling = P.getPreprocessor ().getSpelling (FirstTok);
55
93
56
- OpenACCDirectiveKind DirKind = GetOpenACCDirectiveKind (FirstTokSpelling);
94
+ OpenACCDirectiveKind DirKind = getOpenACCDirectiveKind (FirstTokSpelling);
57
95
58
96
if (DirKind == OpenACCDirectiveKind::Invalid)
59
97
P.Diag (FirstTok, diag::err_acc_invalid_directive) << FirstTokSpelling;
60
98
99
+ // Combined Constructs allows parallel loop, serial loop, or kernels loop. Any
100
+ // other attempt at a combined construct will be diagnosed as an invalid
101
+ // clause.
102
+ Token SecondTok = P.getCurToken ();
103
+ if (!SecondTok.isAnnotation () &&
104
+ isOpenACCDirectiveKind (OpenACCDirectiveKind::Loop,
105
+ P.getPreprocessor ().getSpelling (SecondTok))) {
106
+ switch (DirKind) {
107
+ default :
108
+ // Nothing to do except in the below cases, as they should be diagnosed as
109
+ // a clause.
110
+ break ;
111
+ case OpenACCDirectiveKind::Parallel:
112
+ P.ConsumeToken ();
113
+ return OpenACCDirectiveKind::ParallelLoop;
114
+ case OpenACCDirectiveKind::Serial:
115
+ P.ConsumeToken ();
116
+ return OpenACCDirectiveKind::SerialLoop;
117
+ case OpenACCDirectiveKind::Kernels:
118
+ P.ConsumeToken ();
119
+ return OpenACCDirectiveKind::KernelsLoop;
120
+ }
121
+ }
122
+
61
123
return DirKind;
62
124
}
63
125
0 commit comments