1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
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 /// \file
9 /// This file implements parsing of all OpenMP directives and clauses.
10 ///
11 //===----------------------------------------------------------------------===//
12
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/StmtOpenMP.h"
15 #include "clang/Basic/OpenMPKinds.h"
16 #include "clang/Parse/ParseDiagnostic.h"
17 #include "clang/Parse/Parser.h"
18 #include "clang/Parse/RAIIObjectsForParser.h"
19 #include "clang/Sema/Scope.h"
20 #include "llvm/ADT/PointerIntPair.h"
21 #include "llvm/ADT/UniqueVector.h"
22
23 using namespace clang;
24 using namespace llvm::omp;
25
26 //===----------------------------------------------------------------------===//
27 // OpenMP declarative directives.
28 //===----------------------------------------------------------------------===//
29
30 namespace {
31 enum OpenMPDirectiveKindEx {
32 OMPD_cancellation = unsigned(OMPD_unknown) + 1,
33 OMPD_data,
34 OMPD_declare,
35 OMPD_end,
36 OMPD_end_declare,
37 OMPD_enter,
38 OMPD_exit,
39 OMPD_point,
40 OMPD_reduction,
41 OMPD_target_enter,
42 OMPD_target_exit,
43 OMPD_update,
44 OMPD_distribute_parallel,
45 OMPD_teams_distribute_parallel,
46 OMPD_target_teams_distribute_parallel,
47 OMPD_mapper,
48 OMPD_variant,
49 };
50
51 // Helper to unify the enum class OpenMPDirectiveKind with its extension
52 // the OpenMPDirectiveKindEx enum which allows to use them together as if they
53 // are unsigned values.
54 struct OpenMPDirectiveKindExWrapper {
OpenMPDirectiveKindExWrapper__anon415eeaf70111::OpenMPDirectiveKindExWrapper55 OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
OpenMPDirectiveKindExWrapper__anon415eeaf70111::OpenMPDirectiveKindExWrapper56 OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
operator ==__anon415eeaf70111::OpenMPDirectiveKindExWrapper57 bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
operator !=__anon415eeaf70111::OpenMPDirectiveKindExWrapper58 bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
operator <__anon415eeaf70111::OpenMPDirectiveKindExWrapper59 bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
operator unsigned__anon415eeaf70111::OpenMPDirectiveKindExWrapper60 operator unsigned() const { return Value; }
operator OpenMPDirectiveKind__anon415eeaf70111::OpenMPDirectiveKindExWrapper61 operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
62 unsigned Value;
63 };
64
65 class DeclDirectiveListParserHelper final {
66 SmallVector<Expr *, 4> Identifiers;
67 Parser *P;
68 OpenMPDirectiveKind Kind;
69
70 public:
DeclDirectiveListParserHelper(Parser * P,OpenMPDirectiveKind Kind)71 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
72 : P(P), Kind(Kind) {}
operator ()(CXXScopeSpec & SS,DeclarationNameInfo NameInfo)73 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
74 ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
75 P->getCurScope(), SS, NameInfo, Kind);
76 if (Res.isUsable())
77 Identifiers.push_back(Res.get());
78 }
getIdentifiers() const79 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
80 };
81 } // namespace
82
83 // Map token string to extended OMP token kind that are
84 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
getOpenMPDirectiveKindEx(StringRef S)85 static unsigned getOpenMPDirectiveKindEx(StringRef S) {
86 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
87 if (DKind != OMPD_unknown)
88 return DKind;
89
90 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
91 .Case("cancellation", OMPD_cancellation)
92 .Case("data", OMPD_data)
93 .Case("declare", OMPD_declare)
94 .Case("end", OMPD_end)
95 .Case("enter", OMPD_enter)
96 .Case("exit", OMPD_exit)
97 .Case("point", OMPD_point)
98 .Case("reduction", OMPD_reduction)
99 .Case("update", OMPD_update)
100 .Case("mapper", OMPD_mapper)
101 .Case("variant", OMPD_variant)
102 .Default(OMPD_unknown);
103 }
104
parseOpenMPDirectiveKind(Parser & P)105 static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
106 // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
107 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
108 // TODO: add other combined directives in topological order.
109 static const OpenMPDirectiveKindExWrapper F[][3] = {
110 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
111 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
112 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
113 {OMPD_declare, OMPD_simd, OMPD_declare_simd},
114 {OMPD_declare, OMPD_target, OMPD_declare_target},
115 {OMPD_declare, OMPD_variant, OMPD_declare_variant},
116 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
117 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
118 {OMPD_distribute_parallel_for, OMPD_simd,
119 OMPD_distribute_parallel_for_simd},
120 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
121 {OMPD_end, OMPD_declare, OMPD_end_declare},
122 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
123 {OMPD_target, OMPD_data, OMPD_target_data},
124 {OMPD_target, OMPD_enter, OMPD_target_enter},
125 {OMPD_target, OMPD_exit, OMPD_target_exit},
126 {OMPD_target, OMPD_update, OMPD_target_update},
127 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
128 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
129 {OMPD_for, OMPD_simd, OMPD_for_simd},
130 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
131 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
132 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
133 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
134 {OMPD_target, OMPD_parallel, OMPD_target_parallel},
135 {OMPD_target, OMPD_simd, OMPD_target_simd},
136 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
137 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
138 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
139 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
140 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
141 {OMPD_teams_distribute_parallel, OMPD_for,
142 OMPD_teams_distribute_parallel_for},
143 {OMPD_teams_distribute_parallel_for, OMPD_simd,
144 OMPD_teams_distribute_parallel_for_simd},
145 {OMPD_target, OMPD_teams, OMPD_target_teams},
146 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
147 {OMPD_target_teams_distribute, OMPD_parallel,
148 OMPD_target_teams_distribute_parallel},
149 {OMPD_target_teams_distribute, OMPD_simd,
150 OMPD_target_teams_distribute_simd},
151 {OMPD_target_teams_distribute_parallel, OMPD_for,
152 OMPD_target_teams_distribute_parallel_for},
153 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
154 OMPD_target_teams_distribute_parallel_for_simd},
155 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
156 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
157 {OMPD_parallel, OMPD_master, OMPD_parallel_master},
158 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
159 {OMPD_parallel_master_taskloop, OMPD_simd,
160 OMPD_parallel_master_taskloop_simd}};
161 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
162 Token Tok = P.getCurToken();
163 OpenMPDirectiveKindExWrapper DKind =
164 Tok.isAnnotation()
165 ? static_cast<unsigned>(OMPD_unknown)
166 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
167 if (DKind == OMPD_unknown)
168 return OMPD_unknown;
169
170 for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
171 if (DKind != F[I][0])
172 continue;
173
174 Tok = P.getPreprocessor().LookAhead(0);
175 OpenMPDirectiveKindExWrapper SDKind =
176 Tok.isAnnotation()
177 ? static_cast<unsigned>(OMPD_unknown)
178 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
179 if (SDKind == OMPD_unknown)
180 continue;
181
182 if (SDKind == F[I][1]) {
183 P.ConsumeToken();
184 DKind = F[I][2];
185 }
186 }
187 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
188 : OMPD_unknown;
189 }
190
parseOpenMPReductionId(Parser & P)191 static DeclarationName parseOpenMPReductionId(Parser &P) {
192 Token Tok = P.getCurToken();
193 Sema &Actions = P.getActions();
194 OverloadedOperatorKind OOK = OO_None;
195 // Allow to use 'operator' keyword for C++ operators
196 bool WithOperator = false;
197 if (Tok.is(tok::kw_operator)) {
198 P.ConsumeToken();
199 Tok = P.getCurToken();
200 WithOperator = true;
201 }
202 switch (Tok.getKind()) {
203 case tok::plus: // '+'
204 OOK = OO_Plus;
205 break;
206 case tok::minus: // '-'
207 OOK = OO_Minus;
208 break;
209 case tok::star: // '*'
210 OOK = OO_Star;
211 break;
212 case tok::amp: // '&'
213 OOK = OO_Amp;
214 break;
215 case tok::pipe: // '|'
216 OOK = OO_Pipe;
217 break;
218 case tok::caret: // '^'
219 OOK = OO_Caret;
220 break;
221 case tok::ampamp: // '&&'
222 OOK = OO_AmpAmp;
223 break;
224 case tok::pipepipe: // '||'
225 OOK = OO_PipePipe;
226 break;
227 case tok::identifier: // identifier
228 if (!WithOperator)
229 break;
230 LLVM_FALLTHROUGH;
231 default:
232 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
233 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
234 Parser::StopBeforeMatch);
235 return DeclarationName();
236 }
237 P.ConsumeToken();
238 auto &DeclNames = Actions.getASTContext().DeclarationNames;
239 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
240 : DeclNames.getCXXOperatorName(OOK);
241 }
242
243 /// Parse 'omp declare reduction' construct.
244 ///
245 /// declare-reduction-directive:
246 /// annot_pragma_openmp 'declare' 'reduction'
247 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
248 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
249 /// annot_pragma_openmp_end
250 /// <reduction_id> is either a base language identifier or one of the following
251 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
252 ///
253 Parser::DeclGroupPtrTy
ParseOpenMPDeclareReductionDirective(AccessSpecifier AS)254 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
255 // Parse '('.
256 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
257 if (T.expectAndConsume(
258 diag::err_expected_lparen_after,
259 getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
260 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
261 return DeclGroupPtrTy();
262 }
263
264 DeclarationName Name = parseOpenMPReductionId(*this);
265 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
266 return DeclGroupPtrTy();
267
268 // Consume ':'.
269 bool IsCorrect = !ExpectAndConsume(tok::colon);
270
271 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
272 return DeclGroupPtrTy();
273
274 IsCorrect = IsCorrect && !Name.isEmpty();
275
276 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
277 Diag(Tok.getLocation(), diag::err_expected_type);
278 IsCorrect = false;
279 }
280
281 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
282 return DeclGroupPtrTy();
283
284 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
285 // Parse list of types until ':' token.
286 do {
287 ColonProtectionRAIIObject ColonRAII(*this);
288 SourceRange Range;
289 TypeResult TR =
290 ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
291 if (TR.isUsable()) {
292 QualType ReductionType =
293 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
294 if (!ReductionType.isNull()) {
295 ReductionTypes.push_back(
296 std::make_pair(ReductionType, Range.getBegin()));
297 }
298 } else {
299 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
300 StopBeforeMatch);
301 }
302
303 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
304 break;
305
306 // Consume ','.
307 if (ExpectAndConsume(tok::comma)) {
308 IsCorrect = false;
309 if (Tok.is(tok::annot_pragma_openmp_end)) {
310 Diag(Tok.getLocation(), diag::err_expected_type);
311 return DeclGroupPtrTy();
312 }
313 }
314 } while (Tok.isNot(tok::annot_pragma_openmp_end));
315
316 if (ReductionTypes.empty()) {
317 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
318 return DeclGroupPtrTy();
319 }
320
321 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
322 return DeclGroupPtrTy();
323
324 // Consume ':'.
325 if (ExpectAndConsume(tok::colon))
326 IsCorrect = false;
327
328 if (Tok.is(tok::annot_pragma_openmp_end)) {
329 Diag(Tok.getLocation(), diag::err_expected_expression);
330 return DeclGroupPtrTy();
331 }
332
333 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
334 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
335
336 // Parse <combiner> expression and then parse initializer if any for each
337 // correct type.
338 unsigned I = 0, E = ReductionTypes.size();
339 for (Decl *D : DRD.get()) {
340 TentativeParsingAction TPA(*this);
341 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
342 Scope::CompoundStmtScope |
343 Scope::OpenMPDirectiveScope);
344 // Parse <combiner> expression.
345 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
346 ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
347 ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
348 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
349
350 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
351 Tok.isNot(tok::annot_pragma_openmp_end)) {
352 TPA.Commit();
353 IsCorrect = false;
354 break;
355 }
356 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
357 ExprResult InitializerResult;
358 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
359 // Parse <initializer> expression.
360 if (Tok.is(tok::identifier) &&
361 Tok.getIdentifierInfo()->isStr("initializer")) {
362 ConsumeToken();
363 } else {
364 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
365 TPA.Commit();
366 IsCorrect = false;
367 break;
368 }
369 // Parse '('.
370 BalancedDelimiterTracker T(*this, tok::l_paren,
371 tok::annot_pragma_openmp_end);
372 IsCorrect =
373 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
374 IsCorrect;
375 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
376 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
377 Scope::CompoundStmtScope |
378 Scope::OpenMPDirectiveScope);
379 // Parse expression.
380 VarDecl *OmpPrivParm =
381 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
382 D);
383 // Check if initializer is omp_priv <init_expr> or something else.
384 if (Tok.is(tok::identifier) &&
385 Tok.getIdentifierInfo()->isStr("omp_priv")) {
386 ConsumeToken();
387 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
388 } else {
389 InitializerResult = Actions.ActOnFinishFullExpr(
390 ParseAssignmentExpression().get(), D->getLocation(),
391 /*DiscardedValue*/ false);
392 }
393 Actions.ActOnOpenMPDeclareReductionInitializerEnd(
394 D, InitializerResult.get(), OmpPrivParm);
395 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
396 Tok.isNot(tok::annot_pragma_openmp_end)) {
397 TPA.Commit();
398 IsCorrect = false;
399 break;
400 }
401 IsCorrect =
402 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
403 }
404 }
405
406 ++I;
407 // Revert parsing if not the last type, otherwise accept it, we're done with
408 // parsing.
409 if (I != E)
410 TPA.Revert();
411 else
412 TPA.Commit();
413 }
414 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
415 IsCorrect);
416 }
417
ParseOpenMPReductionInitializerForDecl(VarDecl * OmpPrivParm)418 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
419 // Parse declarator '=' initializer.
420 // If a '==' or '+=' is found, suggest a fixit to '='.
421 if (isTokenEqualOrEqualTypo()) {
422 ConsumeToken();
423
424 if (Tok.is(tok::code_completion)) {
425 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
426 Actions.FinalizeDeclaration(OmpPrivParm);
427 cutOffParsing();
428 return;
429 }
430
431 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
432 ExprResult Init = ParseInitializer();
433
434 if (Init.isInvalid()) {
435 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
436 Actions.ActOnInitializerError(OmpPrivParm);
437 } else {
438 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
439 /*DirectInit=*/false);
440 }
441 } else if (Tok.is(tok::l_paren)) {
442 // Parse C++ direct initializer: '(' expression-list ')'
443 BalancedDelimiterTracker T(*this, tok::l_paren);
444 T.consumeOpen();
445
446 ExprVector Exprs;
447 CommaLocsTy CommaLocs;
448
449 SourceLocation LParLoc = T.getOpenLocation();
450 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
451 QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
452 getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
453 OmpPrivParm->getLocation(), Exprs, LParLoc);
454 CalledSignatureHelp = true;
455 return PreferredType;
456 };
457 if (ParseExpressionList(Exprs, CommaLocs, [&] {
458 PreferredType.enterFunctionArgument(Tok.getLocation(),
459 RunSignatureHelp);
460 })) {
461 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
462 RunSignatureHelp();
463 Actions.ActOnInitializerError(OmpPrivParm);
464 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
465 } else {
466 // Match the ')'.
467 SourceLocation RLoc = Tok.getLocation();
468 if (!T.consumeClose())
469 RLoc = T.getCloseLocation();
470
471 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
472 "Unexpected number of commas!");
473
474 ExprResult Initializer =
475 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
476 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
477 /*DirectInit=*/true);
478 }
479 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
480 // Parse C++0x braced-init-list.
481 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
482
483 ExprResult Init(ParseBraceInitializer());
484
485 if (Init.isInvalid()) {
486 Actions.ActOnInitializerError(OmpPrivParm);
487 } else {
488 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
489 /*DirectInit=*/true);
490 }
491 } else {
492 Actions.ActOnUninitializedDecl(OmpPrivParm);
493 }
494 }
495
496 /// Parses 'omp declare mapper' directive.
497 ///
498 /// declare-mapper-directive:
499 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
500 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
501 /// annot_pragma_openmp_end
502 /// <mapper-identifier> and <var> are base language identifiers.
503 ///
504 Parser::DeclGroupPtrTy
ParseOpenMPDeclareMapperDirective(AccessSpecifier AS)505 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
506 bool IsCorrect = true;
507 // Parse '('
508 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
509 if (T.expectAndConsume(diag::err_expected_lparen_after,
510 getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
511 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
512 return DeclGroupPtrTy();
513 }
514
515 // Parse <mapper-identifier>
516 auto &DeclNames = Actions.getASTContext().DeclarationNames;
517 DeclarationName MapperId;
518 if (PP.LookAhead(0).is(tok::colon)) {
519 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
520 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
521 IsCorrect = false;
522 } else {
523 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
524 }
525 ConsumeToken();
526 // Consume ':'.
527 ExpectAndConsume(tok::colon);
528 } else {
529 // If no mapper identifier is provided, its name is "default" by default
530 MapperId =
531 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
532 }
533
534 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
535 return DeclGroupPtrTy();
536
537 // Parse <type> <var>
538 DeclarationName VName;
539 QualType MapperType;
540 SourceRange Range;
541 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
542 if (ParsedType.isUsable())
543 MapperType =
544 Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
545 if (MapperType.isNull())
546 IsCorrect = false;
547 if (!IsCorrect) {
548 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
549 return DeclGroupPtrTy();
550 }
551
552 // Consume ')'.
553 IsCorrect &= !T.consumeClose();
554 if (!IsCorrect) {
555 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
556 return DeclGroupPtrTy();
557 }
558
559 // Enter scope.
560 OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
561 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
562 Range.getBegin(), VName, AS);
563 DeclarationNameInfo DirName;
564 SourceLocation Loc = Tok.getLocation();
565 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
566 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
567 ParseScope OMPDirectiveScope(this, ScopeFlags);
568 Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
569
570 // Add the mapper variable declaration.
571 Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
572 DMD, getCurScope(), MapperType, Range.getBegin(), VName);
573
574 // Parse map clauses.
575 SmallVector<OMPClause *, 6> Clauses;
576 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
577 OpenMPClauseKind CKind = Tok.isAnnotation()
578 ? OMPC_unknown
579 : getOpenMPClauseKind(PP.getSpelling(Tok));
580 Actions.StartOpenMPClause(CKind);
581 OMPClause *Clause =
582 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
583 if (Clause)
584 Clauses.push_back(Clause);
585 else
586 IsCorrect = false;
587 // Skip ',' if any.
588 if (Tok.is(tok::comma))
589 ConsumeToken();
590 Actions.EndOpenMPClause();
591 }
592 if (Clauses.empty()) {
593 Diag(Tok, diag::err_omp_expected_clause)
594 << getOpenMPDirectiveName(OMPD_declare_mapper);
595 IsCorrect = false;
596 }
597
598 // Exit scope.
599 Actions.EndOpenMPDSABlock(nullptr);
600 OMPDirectiveScope.Exit();
601
602 DeclGroupPtrTy DGP =
603 Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
604 if (!IsCorrect)
605 return DeclGroupPtrTy();
606 return DGP;
607 }
608
parseOpenMPDeclareMapperVarDecl(SourceRange & Range,DeclarationName & Name,AccessSpecifier AS)609 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
610 DeclarationName &Name,
611 AccessSpecifier AS) {
612 // Parse the common declaration-specifiers piece.
613 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
614 DeclSpec DS(AttrFactory);
615 ParseSpecifierQualifierList(DS, AS, DSC);
616
617 // Parse the declarator.
618 DeclaratorContext Context = DeclaratorContext::PrototypeContext;
619 Declarator DeclaratorInfo(DS, Context);
620 ParseDeclarator(DeclaratorInfo);
621 Range = DeclaratorInfo.getSourceRange();
622 if (DeclaratorInfo.getIdentifier() == nullptr) {
623 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
624 return true;
625 }
626 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
627
628 return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
629 }
630
631 namespace {
632 /// RAII that recreates function context for correct parsing of clauses of
633 /// 'declare simd' construct.
634 /// OpenMP, 2.8.2 declare simd Construct
635 /// The expressions appearing in the clauses of this directive are evaluated in
636 /// the scope of the arguments of the function declaration or definition.
637 class FNContextRAII final {
638 Parser &P;
639 Sema::CXXThisScopeRAII *ThisScope;
640 Parser::ParseScope *TempScope;
641 Parser::ParseScope *FnScope;
642 bool HasTemplateScope = false;
643 bool HasFunScope = false;
644 FNContextRAII() = delete;
645 FNContextRAII(const FNContextRAII &) = delete;
646 FNContextRAII &operator=(const FNContextRAII &) = delete;
647
648 public:
FNContextRAII(Parser & P,Parser::DeclGroupPtrTy Ptr)649 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
650 Decl *D = *Ptr.get().begin();
651 NamedDecl *ND = dyn_cast<NamedDecl>(D);
652 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
653 Sema &Actions = P.getActions();
654
655 // Allow 'this' within late-parsed attributes.
656 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
657 ND && ND->isCXXInstanceMember());
658
659 // If the Decl is templatized, add template parameters to scope.
660 HasTemplateScope = D->isTemplateDecl();
661 TempScope =
662 new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
663 if (HasTemplateScope)
664 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
665
666 // If the Decl is on a function, add function parameters to the scope.
667 HasFunScope = D->isFunctionOrFunctionTemplate();
668 FnScope = new Parser::ParseScope(
669 &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
670 HasFunScope);
671 if (HasFunScope)
672 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
673 }
~FNContextRAII()674 ~FNContextRAII() {
675 if (HasFunScope) {
676 P.getActions().ActOnExitFunctionContext();
677 FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
678 }
679 if (HasTemplateScope)
680 TempScope->Exit();
681 delete FnScope;
682 delete TempScope;
683 delete ThisScope;
684 }
685 };
686 } // namespace
687
688 /// Parses clauses for 'declare simd' directive.
689 /// clause:
690 /// 'inbranch' | 'notinbranch'
691 /// 'simdlen' '(' <expr> ')'
692 /// { 'uniform' '(' <argument_list> ')' }
693 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
694 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
parseDeclareSimdClauses(Parser & P,OMPDeclareSimdDeclAttr::BranchStateTy & BS,ExprResult & SimdLen,SmallVectorImpl<Expr * > & Uniforms,SmallVectorImpl<Expr * > & Aligneds,SmallVectorImpl<Expr * > & Alignments,SmallVectorImpl<Expr * > & Linears,SmallVectorImpl<unsigned> & LinModifiers,SmallVectorImpl<Expr * > & Steps)695 static bool parseDeclareSimdClauses(
696 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
697 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
698 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
699 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
700 SourceRange BSRange;
701 const Token &Tok = P.getCurToken();
702 bool IsError = false;
703 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
704 if (Tok.isNot(tok::identifier))
705 break;
706 OMPDeclareSimdDeclAttr::BranchStateTy Out;
707 IdentifierInfo *II = Tok.getIdentifierInfo();
708 StringRef ClauseName = II->getName();
709 // Parse 'inranch|notinbranch' clauses.
710 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
711 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
712 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
713 << ClauseName
714 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
715 IsError = true;
716 }
717 BS = Out;
718 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
719 P.ConsumeToken();
720 } else if (ClauseName.equals("simdlen")) {
721 if (SimdLen.isUsable()) {
722 P.Diag(Tok, diag::err_omp_more_one_clause)
723 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
724 IsError = true;
725 }
726 P.ConsumeToken();
727 SourceLocation RLoc;
728 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
729 if (SimdLen.isInvalid())
730 IsError = true;
731 } else {
732 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
733 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
734 CKind == OMPC_linear) {
735 Parser::OpenMPVarListDataTy Data;
736 SmallVectorImpl<Expr *> *Vars = &Uniforms;
737 if (CKind == OMPC_aligned) {
738 Vars = &Aligneds;
739 } else if (CKind == OMPC_linear) {
740 Data.ExtraModifier = OMPC_LINEAR_val;
741 Vars = &Linears;
742 }
743
744 P.ConsumeToken();
745 if (P.ParseOpenMPVarList(OMPD_declare_simd,
746 getOpenMPClauseKind(ClauseName), *Vars, Data))
747 IsError = true;
748 if (CKind == OMPC_aligned) {
749 Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
750 } else if (CKind == OMPC_linear) {
751 assert(0 <= Data.ExtraModifier &&
752 Data.ExtraModifier <= OMPC_LINEAR_unknown &&
753 "Unexpected linear modifier.");
754 if (P.getActions().CheckOpenMPLinearModifier(
755 static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
756 Data.DepLinMapLastLoc))
757 Data.ExtraModifier = OMPC_LINEAR_val;
758 LinModifiers.append(Linears.size() - LinModifiers.size(),
759 Data.ExtraModifier);
760 Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
761 }
762 } else
763 // TODO: add parsing of other clauses.
764 break;
765 }
766 // Skip ',' if any.
767 if (Tok.is(tok::comma))
768 P.ConsumeToken();
769 }
770 return IsError;
771 }
772
773 /// Parse clauses for '#pragma omp declare simd'.
774 Parser::DeclGroupPtrTy
ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,CachedTokens & Toks,SourceLocation Loc)775 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
776 CachedTokens &Toks, SourceLocation Loc) {
777 PP.EnterToken(Tok, /*IsReinject*/ true);
778 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
779 /*IsReinject*/ true);
780 // Consume the previously pushed token.
781 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
782 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
783
784 FNContextRAII FnContext(*this, Ptr);
785 OMPDeclareSimdDeclAttr::BranchStateTy BS =
786 OMPDeclareSimdDeclAttr::BS_Undefined;
787 ExprResult Simdlen;
788 SmallVector<Expr *, 4> Uniforms;
789 SmallVector<Expr *, 4> Aligneds;
790 SmallVector<Expr *, 4> Alignments;
791 SmallVector<Expr *, 4> Linears;
792 SmallVector<unsigned, 4> LinModifiers;
793 SmallVector<Expr *, 4> Steps;
794 bool IsError =
795 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
796 Alignments, Linears, LinModifiers, Steps);
797 // Need to check for extra tokens.
798 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
799 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
800 << getOpenMPDirectiveName(OMPD_declare_simd);
801 while (Tok.isNot(tok::annot_pragma_openmp_end))
802 ConsumeAnyToken();
803 }
804 // Skip the last annot_pragma_openmp_end.
805 SourceLocation EndLoc = ConsumeAnnotationToken();
806 if (IsError)
807 return Ptr;
808 return Actions.ActOnOpenMPDeclareSimdDirective(
809 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
810 LinModifiers, Steps, SourceRange(Loc, EndLoc));
811 }
812
813 /// Parse optional 'score' '(' <expr> ')' ':'.
parseContextScore(Parser & P)814 static ExprResult parseContextScore(Parser &P) {
815 ExprResult ScoreExpr;
816 Sema::OMPCtxStringType Buffer;
817 StringRef SelectorName =
818 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
819 if (!SelectorName.equals("score"))
820 return ScoreExpr;
821 (void)P.ConsumeToken();
822 SourceLocation RLoc;
823 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
824 // Parse ':'
825 if (P.getCurToken().is(tok::colon))
826 (void)P.ConsumeAnyToken();
827 else
828 P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon)
829 << "context selector score clause";
830 return ScoreExpr;
831 }
832
833 /// Parse context selector for 'implementation' selector set:
834 /// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
835 /// ')'
836 static void
parseImplementationSelector(Parser & P,SourceLocation Loc,llvm::StringMap<SourceLocation> & UsedCtx,SmallVectorImpl<Sema::OMPCtxSelectorData> & Data)837 parseImplementationSelector(Parser &P, SourceLocation Loc,
838 llvm::StringMap<SourceLocation> &UsedCtx,
839 SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
840 const Token &Tok = P.getCurToken();
841 // Parse inner context selector set name, if any.
842 if (!Tok.is(tok::identifier)) {
843 P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
844 << "implementation";
845 // Skip until either '}', ')', or end of directive.
846 while (!P.SkipUntil(tok::r_brace, tok::r_paren,
847 tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
848 ;
849 return;
850 }
851 Sema::OMPCtxStringType Buffer;
852 StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
853 auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
854 if (!Res.second) {
855 // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
856 // Each trait-selector-name can only be specified once.
857 P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
858 << CtxSelectorName << "implementation";
859 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
860 << CtxSelectorName;
861 }
862 OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
863 (void)P.ConsumeToken();
864 switch (CSKind) {
865 case OMP_CTX_vendor: {
866 // Parse '('.
867 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
868 (void)T.expectAndConsume(diag::err_expected_lparen_after,
869 CtxSelectorName.data());
870 ExprResult Score = parseContextScore(P);
871 llvm::UniqueVector<Sema::OMPCtxStringType> Vendors;
872 do {
873 // Parse <vendor>.
874 StringRef VendorName;
875 if (Tok.is(tok::identifier)) {
876 Buffer.clear();
877 VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
878 (void)P.ConsumeToken();
879 if (!VendorName.empty())
880 Vendors.insert(VendorName);
881 } else {
882 P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
883 << "vendor identifier"
884 << "vendor"
885 << "implementation";
886 }
887 if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
888 P.Diag(Tok, diag::err_expected_punc)
889 << (VendorName.empty() ? "vendor name" : VendorName);
890 }
891 } while (Tok.is(tok::identifier));
892 // Parse ')'.
893 (void)T.consumeClose();
894 if (!Vendors.empty())
895 Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors);
896 break;
897 }
898 case OMP_CTX_kind:
899 case OMP_CTX_unknown:
900 P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
901 << "implementation";
902 // Skip until either '}', ')', or end of directive.
903 while (!P.SkipUntil(tok::r_brace, tok::r_paren,
904 tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
905 ;
906 return;
907 }
908 }
909
910 /// Parse context selector for 'device' selector set:
911 /// 'kind' '(' <kind> { ',' <kind> } ')'
912 static void
parseDeviceSelector(Parser & P,SourceLocation Loc,llvm::StringMap<SourceLocation> & UsedCtx,SmallVectorImpl<Sema::OMPCtxSelectorData> & Data)913 parseDeviceSelector(Parser &P, SourceLocation Loc,
914 llvm::StringMap<SourceLocation> &UsedCtx,
915 SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
916 const Token &Tok = P.getCurToken();
917 // Parse inner context selector set name, if any.
918 if (!Tok.is(tok::identifier)) {
919 P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
920 << "device";
921 // Skip until either '}', ')', or end of directive.
922 while (!P.SkipUntil(tok::r_brace, tok::r_paren,
923 tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
924 ;
925 return;
926 }
927 Sema::OMPCtxStringType Buffer;
928 StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
929 auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
930 if (!Res.second) {
931 // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
932 // Each trait-selector-name can only be specified once.
933 P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
934 << CtxSelectorName << "device";
935 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
936 << CtxSelectorName;
937 }
938 OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
939 (void)P.ConsumeToken();
940 switch (CSKind) {
941 case OMP_CTX_kind: {
942 // Parse '('.
943 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
944 (void)T.expectAndConsume(diag::err_expected_lparen_after,
945 CtxSelectorName.data());
946 llvm::UniqueVector<Sema::OMPCtxStringType> Kinds;
947 do {
948 // Parse <kind>.
949 StringRef KindName;
950 if (Tok.is(tok::identifier)) {
951 Buffer.clear();
952 KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
953 SourceLocation SLoc = P.getCurToken().getLocation();
954 (void)P.ConsumeToken();
955 if (llvm::StringSwitch<bool>(KindName)
956 .Case("host", false)
957 .Case("nohost", false)
958 .Case("cpu", false)
959 .Case("gpu", false)
960 .Case("fpga", false)
961 .Default(true)) {
962 P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName;
963 } else {
964 Kinds.insert(KindName);
965 }
966 } else {
967 P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
968 << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'"
969 << "kind"
970 << "device";
971 }
972 if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
973 P.Diag(Tok, diag::err_expected_punc)
974 << (KindName.empty() ? "kind of device" : KindName);
975 }
976 } while (Tok.is(tok::identifier));
977 // Parse ')'.
978 (void)T.consumeClose();
979 if (!Kinds.empty())
980 Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds);
981 break;
982 }
983 case OMP_CTX_vendor:
984 case OMP_CTX_unknown:
985 P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
986 << "device";
987 // Skip until either '}', ')', or end of directive.
988 while (!P.SkipUntil(tok::r_brace, tok::r_paren,
989 tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
990 ;
991 return;
992 }
993 }
994
995 /// Parses clauses for 'declare variant' directive.
996 /// clause:
997 /// <selector_set_name> '=' '{' <context_selectors> '}'
998 /// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
parseOpenMPContextSelectors(SourceLocation Loc,SmallVectorImpl<Sema::OMPCtxSelectorData> & Data)999 bool Parser::parseOpenMPContextSelectors(
1000 SourceLocation Loc, SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
1001 llvm::StringMap<SourceLocation> UsedCtxSets;
1002 do {
1003 // Parse inner context selector set name.
1004 if (!Tok.is(tok::identifier)) {
1005 Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
1006 << getOpenMPClauseName(OMPC_match);
1007 return true;
1008 }
1009 Sema::OMPCtxStringType Buffer;
1010 StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
1011 auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation());
1012 if (!Res.second) {
1013 // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
1014 // Each trait-set-selector-name can only be specified once.
1015 Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use)
1016 << CtxSelectorSetName;
1017 Diag(Res.first->getValue(),
1018 diag::note_omp_declare_variant_ctx_set_used_here)
1019 << CtxSelectorSetName;
1020 }
1021 // Parse '='.
1022 (void)ConsumeToken();
1023 if (Tok.isNot(tok::equal)) {
1024 Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
1025 << CtxSelectorSetName;
1026 return true;
1027 }
1028 (void)ConsumeToken();
1029 // TBD: add parsing of known context selectors.
1030 // Unknown selector - just ignore it completely.
1031 {
1032 // Parse '{'.
1033 BalancedDelimiterTracker TBr(*this, tok::l_brace,
1034 tok::annot_pragma_openmp_end);
1035 if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
1036 return true;
1037 OpenMPContextSelectorSetKind CSSKind =
1038 getOpenMPContextSelectorSet(CtxSelectorSetName);
1039 llvm::StringMap<SourceLocation> UsedCtx;
1040 do {
1041 switch (CSSKind) {
1042 case OMP_CTX_SET_implementation:
1043 parseImplementationSelector(*this, Loc, UsedCtx, Data);
1044 break;
1045 case OMP_CTX_SET_device:
1046 parseDeviceSelector(*this, Loc, UsedCtx, Data);
1047 break;
1048 case OMP_CTX_SET_unknown:
1049 // Skip until either '}', ')', or end of directive.
1050 while (!SkipUntil(tok::r_brace, tok::r_paren,
1051 tok::annot_pragma_openmp_end, StopBeforeMatch))
1052 ;
1053 break;
1054 }
1055 const Token PrevTok = Tok;
1056 if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
1057 Diag(Tok, diag::err_omp_expected_comma_brace)
1058 << (PrevTok.isAnnotation() ? "context selector trait"
1059 : PP.getSpelling(PrevTok));
1060 } while (Tok.is(tok::identifier));
1061 // Parse '}'.
1062 (void)TBr.consumeClose();
1063 }
1064 // Consume ','
1065 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end))
1066 (void)ExpectAndConsume(tok::comma);
1067 } while (Tok.isAnyIdentifier());
1068 return false;
1069 }
1070
1071 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,CachedTokens & Toks,SourceLocation Loc)1072 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1073 CachedTokens &Toks,
1074 SourceLocation Loc) {
1075 PP.EnterToken(Tok, /*IsReinject*/ true);
1076 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1077 /*IsReinject*/ true);
1078 // Consume the previously pushed token.
1079 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1080 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1081
1082 FNContextRAII FnContext(*this, Ptr);
1083 // Parse function declaration id.
1084 SourceLocation RLoc;
1085 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1086 // instead of MemberExprs.
1087 ExprResult AssociatedFunction;
1088 {
1089 // Do not mark function as is used to prevent its emission if this is the
1090 // only place where it is used.
1091 EnterExpressionEvaluationContext Unevaluated(
1092 Actions, Sema::ExpressionEvaluationContext::Unevaluated);
1093 AssociatedFunction = ParseOpenMPParensExpr(
1094 getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1095 /*IsAddressOfOperand=*/true);
1096 }
1097 if (!AssociatedFunction.isUsable()) {
1098 if (!Tok.is(tok::annot_pragma_openmp_end))
1099 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1100 ;
1101 // Skip the last annot_pragma_openmp_end.
1102 (void)ConsumeAnnotationToken();
1103 return;
1104 }
1105 Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1106 Actions.checkOpenMPDeclareVariantFunction(
1107 Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation()));
1108
1109 // Parse 'match'.
1110 OpenMPClauseKind CKind = Tok.isAnnotation()
1111 ? OMPC_unknown
1112 : getOpenMPClauseKind(PP.getSpelling(Tok));
1113 if (CKind != OMPC_match) {
1114 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1115 << getOpenMPClauseName(OMPC_match);
1116 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
1117 ;
1118 // Skip the last annot_pragma_openmp_end.
1119 (void)ConsumeAnnotationToken();
1120 return;
1121 }
1122 (void)ConsumeToken();
1123 // Parse '('.
1124 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1125 if (T.expectAndConsume(diag::err_expected_lparen_after,
1126 getOpenMPClauseName(OMPC_match))) {
1127 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1128 ;
1129 // Skip the last annot_pragma_openmp_end.
1130 (void)ConsumeAnnotationToken();
1131 return;
1132 }
1133
1134 // Parse inner context selectors.
1135 SmallVector<Sema::OMPCtxSelectorData, 4> Data;
1136 if (!parseOpenMPContextSelectors(Loc, Data)) {
1137 // Parse ')'.
1138 (void)T.consumeClose();
1139 // Need to check for extra tokens.
1140 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1141 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1142 << getOpenMPDirectiveName(OMPD_declare_variant);
1143 }
1144 }
1145
1146 // Skip last tokens.
1147 while (Tok.isNot(tok::annot_pragma_openmp_end))
1148 ConsumeAnyToken();
1149 if (DeclVarData.hasValue())
1150 Actions.ActOnOpenMPDeclareVariantDirective(
1151 DeclVarData.getValue().first, DeclVarData.getValue().second,
1152 SourceRange(Loc, Tok.getLocation()), Data);
1153 // Skip the last annot_pragma_openmp_end.
1154 (void)ConsumeAnnotationToken();
1155 }
1156
1157 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1158 ///
1159 /// default-clause:
1160 /// 'default' '(' 'none' | 'shared' ')
1161 ///
1162 /// proc_bind-clause:
1163 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1164 ///
1165 /// device_type-clause:
1166 /// 'device_type' '(' 'host' | 'nohost' | 'any' )'
1167 namespace {
1168 struct SimpleClauseData {
1169 unsigned Type;
1170 SourceLocation Loc;
1171 SourceLocation LOpen;
1172 SourceLocation TypeLoc;
1173 SourceLocation RLoc;
SimpleClauseData__anon415eeaf70611::SimpleClauseData1174 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1175 SourceLocation TypeLoc, SourceLocation RLoc)
1176 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1177 };
1178 } // anonymous namespace
1179
1180 static Optional<SimpleClauseData>
parseOpenMPSimpleClause(Parser & P,OpenMPClauseKind Kind)1181 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
1182 const Token &Tok = P.getCurToken();
1183 SourceLocation Loc = Tok.getLocation();
1184 SourceLocation LOpen = P.ConsumeToken();
1185 // Parse '('.
1186 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1187 if (T.expectAndConsume(diag::err_expected_lparen_after,
1188 getOpenMPClauseName(Kind)))
1189 return llvm::None;
1190
1191 unsigned Type = getOpenMPSimpleClauseType(
1192 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok));
1193 SourceLocation TypeLoc = Tok.getLocation();
1194 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1195 Tok.isNot(tok::annot_pragma_openmp_end))
1196 P.ConsumeAnyToken();
1197
1198 // Parse ')'.
1199 SourceLocation RLoc = Tok.getLocation();
1200 if (!T.consumeClose())
1201 RLoc = T.getCloseLocation();
1202
1203 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1204 }
1205
ParseOMPDeclareTargetClauses()1206 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
1207 // OpenMP 4.5 syntax with list of entities.
1208 Sema::NamedDeclSetType SameDirectiveDecls;
1209 SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation,
1210 NamedDecl *>,
1211 4>
1212 DeclareTargetDecls;
1213 OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
1214 SourceLocation DeviceTypeLoc;
1215 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1216 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1217 if (Tok.is(tok::identifier)) {
1218 IdentifierInfo *II = Tok.getIdentifierInfo();
1219 StringRef ClauseName = II->getName();
1220 bool IsDeviceTypeClause =
1221 getLangOpts().OpenMP >= 50 &&
1222 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1223 // Parse 'to|link|device_type' clauses.
1224 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
1225 !IsDeviceTypeClause) {
1226 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1227 << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
1228 break;
1229 }
1230 // Parse 'device_type' clause and go to next clause if any.
1231 if (IsDeviceTypeClause) {
1232 Optional<SimpleClauseData> DevTypeData =
1233 parseOpenMPSimpleClause(*this, OMPC_device_type);
1234 if (DevTypeData.hasValue()) {
1235 if (DeviceTypeLoc.isValid()) {
1236 // We already saw another device_type clause, diagnose it.
1237 Diag(DevTypeData.getValue().Loc,
1238 diag::warn_omp_more_one_device_type_clause);
1239 }
1240 switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
1241 case OMPC_DEVICE_TYPE_any:
1242 DT = OMPDeclareTargetDeclAttr::DT_Any;
1243 break;
1244 case OMPC_DEVICE_TYPE_host:
1245 DT = OMPDeclareTargetDeclAttr::DT_Host;
1246 break;
1247 case OMPC_DEVICE_TYPE_nohost:
1248 DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1249 break;
1250 case OMPC_DEVICE_TYPE_unknown:
1251 llvm_unreachable("Unexpected device_type");
1252 }
1253 DeviceTypeLoc = DevTypeData.getValue().Loc;
1254 }
1255 continue;
1256 }
1257 ConsumeToken();
1258 }
1259 auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
1260 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
1261 NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
1262 getCurScope(), SS, NameInfo, SameDirectiveDecls);
1263 if (ND)
1264 DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
1265 };
1266 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1267 /*AllowScopeSpecifier=*/true))
1268 break;
1269
1270 // Consume optional ','.
1271 if (Tok.is(tok::comma))
1272 ConsumeToken();
1273 }
1274 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1275 ConsumeAnyToken();
1276 for (auto &MTLocDecl : DeclareTargetDecls) {
1277 OMPDeclareTargetDeclAttr::MapTypeTy MT;
1278 SourceLocation Loc;
1279 NamedDecl *ND;
1280 std::tie(MT, Loc, ND) = MTLocDecl;
1281 // device_type clause is applied only to functions.
1282 Actions.ActOnOpenMPDeclareTargetName(
1283 ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
1284 }
1285 SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
1286 SameDirectiveDecls.end());
1287 if (Decls.empty())
1288 return DeclGroupPtrTy();
1289 return Actions.BuildDeclaratorGroup(Decls);
1290 }
1291
ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,SourceLocation DTLoc)1292 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
1293 SourceLocation DTLoc) {
1294 if (DKind != OMPD_end_declare_target) {
1295 Diag(Tok, diag::err_expected_end_declare_target);
1296 Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
1297 return;
1298 }
1299 ConsumeAnyToken();
1300 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1301 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1302 << getOpenMPDirectiveName(OMPD_end_declare_target);
1303 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1304 }
1305 // Skip the last annot_pragma_openmp_end.
1306 ConsumeAnyToken();
1307 }
1308
1309 /// Parsing of declarative OpenMP directives.
1310 ///
1311 /// threadprivate-directive:
1312 /// annot_pragma_openmp 'threadprivate' simple-variable-list
1313 /// annot_pragma_openmp_end
1314 ///
1315 /// allocate-directive:
1316 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
1317 /// annot_pragma_openmp_end
1318 ///
1319 /// declare-reduction-directive:
1320 /// annot_pragma_openmp 'declare' 'reduction' [...]
1321 /// annot_pragma_openmp_end
1322 ///
1323 /// declare-mapper-directive:
1324 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1325 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
1326 /// annot_pragma_openmp_end
1327 ///
1328 /// declare-simd-directive:
1329 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
1330 /// annot_pragma_openmp_end
1331 /// <function declaration/definition>
1332 ///
1333 /// requires directive:
1334 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
1335 /// annot_pragma_openmp_end
1336 ///
ParseOpenMPDeclarativeDirectiveWithExtDecl(AccessSpecifier & AS,ParsedAttributesWithRange & Attrs,bool Delayed,DeclSpec::TST TagType,Decl * Tag)1337 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1338 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
1339 DeclSpec::TST TagType, Decl *Tag) {
1340 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1341 ParsingOpenMPDirectiveRAII DirScope(*this);
1342 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1343
1344 SourceLocation Loc;
1345 OpenMPDirectiveKind DKind;
1346 if (Delayed) {
1347 TentativeParsingAction TPA(*this);
1348 Loc = ConsumeAnnotationToken();
1349 DKind = parseOpenMPDirectiveKind(*this);
1350 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1351 // Need to delay parsing until completion of the parent class.
1352 TPA.Revert();
1353 CachedTokens Toks;
1354 unsigned Cnt = 1;
1355 Toks.push_back(Tok);
1356 while (Cnt && Tok.isNot(tok::eof)) {
1357 (void)ConsumeAnyToken();
1358 if (Tok.is(tok::annot_pragma_openmp))
1359 ++Cnt;
1360 else if (Tok.is(tok::annot_pragma_openmp_end))
1361 --Cnt;
1362 Toks.push_back(Tok);
1363 }
1364 // Skip last annot_pragma_openmp_end.
1365 if (Cnt == 0)
1366 (void)ConsumeAnyToken();
1367 auto *LP = new LateParsedPragma(this, AS);
1368 LP->takeToks(Toks);
1369 getCurrentClass().LateParsedDeclarations.push_back(LP);
1370 return nullptr;
1371 }
1372 TPA.Commit();
1373 } else {
1374 Loc = ConsumeAnnotationToken();
1375 DKind = parseOpenMPDirectiveKind(*this);
1376 }
1377
1378 switch (DKind) {
1379 case OMPD_threadprivate: {
1380 ConsumeToken();
1381 DeclDirectiveListParserHelper Helper(this, DKind);
1382 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1383 /*AllowScopeSpecifier=*/true)) {
1384 // The last seen token is annot_pragma_openmp_end - need to check for
1385 // extra tokens.
1386 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1387 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1388 << getOpenMPDirectiveName(DKind);
1389 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1390 }
1391 // Skip the last annot_pragma_openmp_end.
1392 ConsumeAnnotationToken();
1393 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
1394 Helper.getIdentifiers());
1395 }
1396 break;
1397 }
1398 case OMPD_allocate: {
1399 ConsumeToken();
1400 DeclDirectiveListParserHelper Helper(this, DKind);
1401 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1402 /*AllowScopeSpecifier=*/true)) {
1403 SmallVector<OMPClause *, 1> Clauses;
1404 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1405 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1406 OMPC_unknown + 1>
1407 FirstClauses(OMPC_unknown + 1);
1408 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1409 OpenMPClauseKind CKind =
1410 Tok.isAnnotation() ? OMPC_unknown
1411 : getOpenMPClauseKind(PP.getSpelling(Tok));
1412 Actions.StartOpenMPClause(CKind);
1413 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1414 !FirstClauses[CKind].getInt());
1415 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1416 StopBeforeMatch);
1417 FirstClauses[CKind].setInt(true);
1418 if (Clause != nullptr)
1419 Clauses.push_back(Clause);
1420 if (Tok.is(tok::annot_pragma_openmp_end)) {
1421 Actions.EndOpenMPClause();
1422 break;
1423 }
1424 // Skip ',' if any.
1425 if (Tok.is(tok::comma))
1426 ConsumeToken();
1427 Actions.EndOpenMPClause();
1428 }
1429 // The last seen token is annot_pragma_openmp_end - need to check for
1430 // extra tokens.
1431 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1432 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1433 << getOpenMPDirectiveName(DKind);
1434 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1435 }
1436 }
1437 // Skip the last annot_pragma_openmp_end.
1438 ConsumeAnnotationToken();
1439 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
1440 Clauses);
1441 }
1442 break;
1443 }
1444 case OMPD_requires: {
1445 SourceLocation StartLoc = ConsumeToken();
1446 SmallVector<OMPClause *, 5> Clauses;
1447 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
1448 FirstClauses(OMPC_unknown + 1);
1449 if (Tok.is(tok::annot_pragma_openmp_end)) {
1450 Diag(Tok, diag::err_omp_expected_clause)
1451 << getOpenMPDirectiveName(OMPD_requires);
1452 break;
1453 }
1454 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1455 OpenMPClauseKind CKind = Tok.isAnnotation()
1456 ? OMPC_unknown
1457 : getOpenMPClauseKind(PP.getSpelling(Tok));
1458 Actions.StartOpenMPClause(CKind);
1459 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
1460 !FirstClauses[CKind].getInt());
1461 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1462 StopBeforeMatch);
1463 FirstClauses[CKind].setInt(true);
1464 if (Clause != nullptr)
1465 Clauses.push_back(Clause);
1466 if (Tok.is(tok::annot_pragma_openmp_end)) {
1467 Actions.EndOpenMPClause();
1468 break;
1469 }
1470 // Skip ',' if any.
1471 if (Tok.is(tok::comma))
1472 ConsumeToken();
1473 Actions.EndOpenMPClause();
1474 }
1475 // Consume final annot_pragma_openmp_end
1476 if (Clauses.size() == 0) {
1477 Diag(Tok, diag::err_omp_expected_clause)
1478 << getOpenMPDirectiveName(OMPD_requires);
1479 ConsumeAnnotationToken();
1480 return nullptr;
1481 }
1482 ConsumeAnnotationToken();
1483 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
1484 }
1485 case OMPD_declare_reduction:
1486 ConsumeToken();
1487 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
1488 // The last seen token is annot_pragma_openmp_end - need to check for
1489 // extra tokens.
1490 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1491 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1492 << getOpenMPDirectiveName(OMPD_declare_reduction);
1493 while (Tok.isNot(tok::annot_pragma_openmp_end))
1494 ConsumeAnyToken();
1495 }
1496 // Skip the last annot_pragma_openmp_end.
1497 ConsumeAnnotationToken();
1498 return Res;
1499 }
1500 break;
1501 case OMPD_declare_mapper: {
1502 ConsumeToken();
1503 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
1504 // Skip the last annot_pragma_openmp_end.
1505 ConsumeAnnotationToken();
1506 return Res;
1507 }
1508 break;
1509 }
1510 case OMPD_declare_variant:
1511 case OMPD_declare_simd: {
1512 // The syntax is:
1513 // { #pragma omp declare {simd|variant} }
1514 // <function-declaration-or-definition>
1515 //
1516 CachedTokens Toks;
1517 Toks.push_back(Tok);
1518 ConsumeToken();
1519 while(Tok.isNot(tok::annot_pragma_openmp_end)) {
1520 Toks.push_back(Tok);
1521 ConsumeAnyToken();
1522 }
1523 Toks.push_back(Tok);
1524 ConsumeAnyToken();
1525
1526 DeclGroupPtrTy Ptr;
1527 if (Tok.is(tok::annot_pragma_openmp)) {
1528 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
1529 TagType, Tag);
1530 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1531 // Here we expect to see some function declaration.
1532 if (AS == AS_none) {
1533 assert(TagType == DeclSpec::TST_unspecified);
1534 MaybeParseCXX11Attributes(Attrs);
1535 ParsingDeclSpec PDS(*this);
1536 Ptr = ParseExternalDeclaration(Attrs, &PDS);
1537 } else {
1538 Ptr =
1539 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1540 }
1541 }
1542 if (!Ptr) {
1543 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
1544 << (DKind == OMPD_declare_simd ? 0 : 1);
1545 return DeclGroupPtrTy();
1546 }
1547 if (DKind == OMPD_declare_simd)
1548 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
1549 assert(DKind == OMPD_declare_variant &&
1550 "Expected declare variant directive only");
1551 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
1552 return Ptr;
1553 }
1554 case OMPD_declare_target: {
1555 SourceLocation DTLoc = ConsumeAnyToken();
1556 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1557 return ParseOMPDeclareTargetClauses();
1558 }
1559
1560 // Skip the last annot_pragma_openmp_end.
1561 ConsumeAnyToken();
1562
1563 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1564 return DeclGroupPtrTy();
1565
1566 llvm::SmallVector<Decl *, 4> Decls;
1567 DKind = parseOpenMPDirectiveKind(*this);
1568 while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
1569 Tok.isNot(tok::r_brace)) {
1570 DeclGroupPtrTy Ptr;
1571 // Here we expect to see some function declaration.
1572 if (AS == AS_none) {
1573 assert(TagType == DeclSpec::TST_unspecified);
1574 MaybeParseCXX11Attributes(Attrs);
1575 ParsingDeclSpec PDS(*this);
1576 Ptr = ParseExternalDeclaration(Attrs, &PDS);
1577 } else {
1578 Ptr =
1579 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1580 }
1581 if (Ptr) {
1582 DeclGroupRef Ref = Ptr.get();
1583 Decls.append(Ref.begin(), Ref.end());
1584 }
1585 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
1586 TentativeParsingAction TPA(*this);
1587 ConsumeAnnotationToken();
1588 DKind = parseOpenMPDirectiveKind(*this);
1589 if (DKind != OMPD_end_declare_target)
1590 TPA.Revert();
1591 else
1592 TPA.Commit();
1593 }
1594 }
1595
1596 ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
1597 Actions.ActOnFinishOpenMPDeclareTargetDirective();
1598 return Actions.BuildDeclaratorGroup(Decls);
1599 }
1600 case OMPD_unknown:
1601 Diag(Tok, diag::err_omp_unknown_directive);
1602 break;
1603 case OMPD_parallel:
1604 case OMPD_simd:
1605 case OMPD_task:
1606 case OMPD_taskyield:
1607 case OMPD_barrier:
1608 case OMPD_taskwait:
1609 case OMPD_taskgroup:
1610 case OMPD_flush:
1611 case OMPD_for:
1612 case OMPD_for_simd:
1613 case OMPD_sections:
1614 case OMPD_section:
1615 case OMPD_single:
1616 case OMPD_master:
1617 case OMPD_ordered:
1618 case OMPD_critical:
1619 case OMPD_parallel_for:
1620 case OMPD_parallel_for_simd:
1621 case OMPD_parallel_sections:
1622 case OMPD_parallel_master:
1623 case OMPD_atomic:
1624 case OMPD_target:
1625 case OMPD_teams:
1626 case OMPD_cancellation_point:
1627 case OMPD_cancel:
1628 case OMPD_target_data:
1629 case OMPD_target_enter_data:
1630 case OMPD_target_exit_data:
1631 case OMPD_target_parallel:
1632 case OMPD_target_parallel_for:
1633 case OMPD_taskloop:
1634 case OMPD_taskloop_simd:
1635 case OMPD_master_taskloop:
1636 case OMPD_master_taskloop_simd:
1637 case OMPD_parallel_master_taskloop:
1638 case OMPD_parallel_master_taskloop_simd:
1639 case OMPD_distribute:
1640 case OMPD_end_declare_target:
1641 case OMPD_target_update:
1642 case OMPD_distribute_parallel_for:
1643 case OMPD_distribute_parallel_for_simd:
1644 case OMPD_distribute_simd:
1645 case OMPD_target_parallel_for_simd:
1646 case OMPD_target_simd:
1647 case OMPD_teams_distribute:
1648 case OMPD_teams_distribute_simd:
1649 case OMPD_teams_distribute_parallel_for_simd:
1650 case OMPD_teams_distribute_parallel_for:
1651 case OMPD_target_teams:
1652 case OMPD_target_teams_distribute:
1653 case OMPD_target_teams_distribute_parallel_for:
1654 case OMPD_target_teams_distribute_parallel_for_simd:
1655 case OMPD_target_teams_distribute_simd:
1656 Diag(Tok, diag::err_omp_unexpected_directive)
1657 << 1 << getOpenMPDirectiveName(DKind);
1658 break;
1659 }
1660 while (Tok.isNot(tok::annot_pragma_openmp_end))
1661 ConsumeAnyToken();
1662 ConsumeAnyToken();
1663 return nullptr;
1664 }
1665
1666 /// Parsing of declarative or executable OpenMP directives.
1667 ///
1668 /// threadprivate-directive:
1669 /// annot_pragma_openmp 'threadprivate' simple-variable-list
1670 /// annot_pragma_openmp_end
1671 ///
1672 /// allocate-directive:
1673 /// annot_pragma_openmp 'allocate' simple-variable-list
1674 /// annot_pragma_openmp_end
1675 ///
1676 /// declare-reduction-directive:
1677 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
1678 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
1679 /// ('omp_priv' '=' <expression>|<function_call>) ')']
1680 /// annot_pragma_openmp_end
1681 ///
1682 /// declare-mapper-directive:
1683 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1684 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
1685 /// annot_pragma_openmp_end
1686 ///
1687 /// executable-directive:
1688 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
1689 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
1690 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
1691 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' |
1692 /// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
1693 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
1694 /// 'master taskloop' | 'master taskloop simd' | 'parallel master
1695 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
1696 /// enter data' | 'target exit data' | 'target parallel' | 'target
1697 /// parallel for' | 'target update' | 'distribute parallel for' |
1698 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel
1699 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute
1700 /// simd' | 'teams distribute parallel for simd' | 'teams distribute
1701 /// parallel for' | 'target teams' | 'target teams distribute' | 'target
1702 /// teams distribute parallel for' | 'target teams distribute parallel
1703 /// for simd' | 'target teams distribute simd' {clause}
1704 /// annot_pragma_openmp_end
1705 ///
1706 StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx)1707 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
1708 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1709 ParsingOpenMPDirectiveRAII DirScope(*this);
1710 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1711 SmallVector<OMPClause *, 5> Clauses;
1712 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
1713 FirstClauses(OMPC_unknown + 1);
1714 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
1715 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
1716 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
1717 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
1718 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
1719 // Name of critical directive.
1720 DeclarationNameInfo DirName;
1721 StmtResult Directive = StmtError();
1722 bool HasAssociatedStatement = true;
1723 bool FlushHasClause = false;
1724
1725 switch (DKind) {
1726 case OMPD_threadprivate: {
1727 // FIXME: Should this be permitted in C++?
1728 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1729 ParsedStmtContext()) {
1730 Diag(Tok, diag::err_omp_immediate_directive)
1731 << getOpenMPDirectiveName(DKind) << 0;
1732 }
1733 ConsumeToken();
1734 DeclDirectiveListParserHelper Helper(this, DKind);
1735 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1736 /*AllowScopeSpecifier=*/false)) {
1737 // The last seen token is annot_pragma_openmp_end - need to check for
1738 // extra tokens.
1739 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1740 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1741 << getOpenMPDirectiveName(DKind);
1742 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1743 }
1744 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
1745 Loc, Helper.getIdentifiers());
1746 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1747 }
1748 SkipUntil(tok::annot_pragma_openmp_end);
1749 break;
1750 }
1751 case OMPD_allocate: {
1752 // FIXME: Should this be permitted in C++?
1753 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1754 ParsedStmtContext()) {
1755 Diag(Tok, diag::err_omp_immediate_directive)
1756 << getOpenMPDirectiveName(DKind) << 0;
1757 }
1758 ConsumeToken();
1759 DeclDirectiveListParserHelper Helper(this, DKind);
1760 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1761 /*AllowScopeSpecifier=*/false)) {
1762 SmallVector<OMPClause *, 1> Clauses;
1763 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1764 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1765 OMPC_unknown + 1>
1766 FirstClauses(OMPC_unknown + 1);
1767 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1768 OpenMPClauseKind CKind =
1769 Tok.isAnnotation() ? OMPC_unknown
1770 : getOpenMPClauseKind(PP.getSpelling(Tok));
1771 Actions.StartOpenMPClause(CKind);
1772 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1773 !FirstClauses[CKind].getInt());
1774 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1775 StopBeforeMatch);
1776 FirstClauses[CKind].setInt(true);
1777 if (Clause != nullptr)
1778 Clauses.push_back(Clause);
1779 if (Tok.is(tok::annot_pragma_openmp_end)) {
1780 Actions.EndOpenMPClause();
1781 break;
1782 }
1783 // Skip ',' if any.
1784 if (Tok.is(tok::comma))
1785 ConsumeToken();
1786 Actions.EndOpenMPClause();
1787 }
1788 // The last seen token is annot_pragma_openmp_end - need to check for
1789 // extra tokens.
1790 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1791 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1792 << getOpenMPDirectiveName(DKind);
1793 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1794 }
1795 }
1796 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
1797 Loc, Helper.getIdentifiers(), Clauses);
1798 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1799 }
1800 SkipUntil(tok::annot_pragma_openmp_end);
1801 break;
1802 }
1803 case OMPD_declare_reduction:
1804 ConsumeToken();
1805 if (DeclGroupPtrTy Res =
1806 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
1807 // The last seen token is annot_pragma_openmp_end - need to check for
1808 // extra tokens.
1809 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1810 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1811 << getOpenMPDirectiveName(OMPD_declare_reduction);
1812 while (Tok.isNot(tok::annot_pragma_openmp_end))
1813 ConsumeAnyToken();
1814 }
1815 ConsumeAnyToken();
1816 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1817 } else {
1818 SkipUntil(tok::annot_pragma_openmp_end);
1819 }
1820 break;
1821 case OMPD_declare_mapper: {
1822 ConsumeToken();
1823 if (DeclGroupPtrTy Res =
1824 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
1825 // Skip the last annot_pragma_openmp_end.
1826 ConsumeAnnotationToken();
1827 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1828 } else {
1829 SkipUntil(tok::annot_pragma_openmp_end);
1830 }
1831 break;
1832 }
1833 case OMPD_flush:
1834 if (PP.LookAhead(0).is(tok::l_paren)) {
1835 FlushHasClause = true;
1836 // Push copy of the current token back to stream to properly parse
1837 // pseudo-clause OMPFlushClause.
1838 PP.EnterToken(Tok, /*IsReinject*/ true);
1839 }
1840 LLVM_FALLTHROUGH;
1841 case OMPD_taskyield:
1842 case OMPD_barrier:
1843 case OMPD_taskwait:
1844 case OMPD_cancellation_point:
1845 case OMPD_cancel:
1846 case OMPD_target_enter_data:
1847 case OMPD_target_exit_data:
1848 case OMPD_target_update:
1849 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1850 ParsedStmtContext()) {
1851 Diag(Tok, diag::err_omp_immediate_directive)
1852 << getOpenMPDirectiveName(DKind) << 0;
1853 }
1854 HasAssociatedStatement = false;
1855 // Fall through for further analysis.
1856 LLVM_FALLTHROUGH;
1857 case OMPD_parallel:
1858 case OMPD_simd:
1859 case OMPD_for:
1860 case OMPD_for_simd:
1861 case OMPD_sections:
1862 case OMPD_single:
1863 case OMPD_section:
1864 case OMPD_master:
1865 case OMPD_critical:
1866 case OMPD_parallel_for:
1867 case OMPD_parallel_for_simd:
1868 case OMPD_parallel_sections:
1869 case OMPD_parallel_master:
1870 case OMPD_task:
1871 case OMPD_ordered:
1872 case OMPD_atomic:
1873 case OMPD_target:
1874 case OMPD_teams:
1875 case OMPD_taskgroup:
1876 case OMPD_target_data:
1877 case OMPD_target_parallel:
1878 case OMPD_target_parallel_for:
1879 case OMPD_taskloop:
1880 case OMPD_taskloop_simd:
1881 case OMPD_master_taskloop:
1882 case OMPD_master_taskloop_simd:
1883 case OMPD_parallel_master_taskloop:
1884 case OMPD_parallel_master_taskloop_simd:
1885 case OMPD_distribute:
1886 case OMPD_distribute_parallel_for:
1887 case OMPD_distribute_parallel_for_simd:
1888 case OMPD_distribute_simd:
1889 case OMPD_target_parallel_for_simd:
1890 case OMPD_target_simd:
1891 case OMPD_teams_distribute:
1892 case OMPD_teams_distribute_simd:
1893 case OMPD_teams_distribute_parallel_for_simd:
1894 case OMPD_teams_distribute_parallel_for:
1895 case OMPD_target_teams:
1896 case OMPD_target_teams_distribute:
1897 case OMPD_target_teams_distribute_parallel_for:
1898 case OMPD_target_teams_distribute_parallel_for_simd:
1899 case OMPD_target_teams_distribute_simd: {
1900 ConsumeToken();
1901 // Parse directive name of the 'critical' directive if any.
1902 if (DKind == OMPD_critical) {
1903 BalancedDelimiterTracker T(*this, tok::l_paren,
1904 tok::annot_pragma_openmp_end);
1905 if (!T.consumeOpen()) {
1906 if (Tok.isAnyIdentifier()) {
1907 DirName =
1908 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
1909 ConsumeAnyToken();
1910 } else {
1911 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
1912 }
1913 T.consumeClose();
1914 }
1915 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1916 CancelRegion = parseOpenMPDirectiveKind(*this);
1917 if (Tok.isNot(tok::annot_pragma_openmp_end))
1918 ConsumeToken();
1919 }
1920
1921 if (isOpenMPLoopDirective(DKind))
1922 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
1923 if (isOpenMPSimdDirective(DKind))
1924 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
1925 ParseScope OMPDirectiveScope(this, ScopeFlags);
1926 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1927
1928 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1929 OpenMPClauseKind CKind =
1930 Tok.isAnnotation()
1931 ? OMPC_unknown
1932 : FlushHasClause ? OMPC_flush
1933 : getOpenMPClauseKind(PP.getSpelling(Tok));
1934 Actions.StartOpenMPClause(CKind);
1935 FlushHasClause = false;
1936 OMPClause *Clause =
1937 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1938 FirstClauses[CKind].setInt(true);
1939 if (Clause) {
1940 FirstClauses[CKind].setPointer(Clause);
1941 Clauses.push_back(Clause);
1942 }
1943
1944 // Skip ',' if any.
1945 if (Tok.is(tok::comma))
1946 ConsumeToken();
1947 Actions.EndOpenMPClause();
1948 }
1949 // End location of the directive.
1950 EndLoc = Tok.getLocation();
1951 // Consume final annot_pragma_openmp_end.
1952 ConsumeAnnotationToken();
1953
1954 // OpenMP [2.13.8, ordered Construct, Syntax]
1955 // If the depend clause is specified, the ordered construct is a stand-alone
1956 // directive.
1957 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1958 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1959 ParsedStmtContext()) {
1960 Diag(Loc, diag::err_omp_immediate_directive)
1961 << getOpenMPDirectiveName(DKind) << 1
1962 << getOpenMPClauseName(OMPC_depend);
1963 }
1964 HasAssociatedStatement = false;
1965 }
1966
1967 StmtResult AssociatedStmt;
1968 if (HasAssociatedStatement) {
1969 // The body is a block scope like in Lambdas and Blocks.
1970 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1971 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
1972 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
1973 // should have at least one compound statement scope within it.
1974 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
1975 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1976 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1977 DKind == OMPD_target_exit_data) {
1978 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1979 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
1980 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
1981 /*isStmtExpr=*/false));
1982 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1983 }
1984 Directive = Actions.ActOnOpenMPExecutableDirective(
1985 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1986 EndLoc);
1987
1988 // Exit scope.
1989 Actions.EndOpenMPDSABlock(Directive.get());
1990 OMPDirectiveScope.Exit();
1991 break;
1992 }
1993 case OMPD_declare_simd:
1994 case OMPD_declare_target:
1995 case OMPD_end_declare_target:
1996 case OMPD_requires:
1997 case OMPD_declare_variant:
1998 Diag(Tok, diag::err_omp_unexpected_directive)
1999 << 1 << getOpenMPDirectiveName(DKind);
2000 SkipUntil(tok::annot_pragma_openmp_end);
2001 break;
2002 case OMPD_unknown:
2003 Diag(Tok, diag::err_omp_unknown_directive);
2004 SkipUntil(tok::annot_pragma_openmp_end);
2005 break;
2006 }
2007 return Directive;
2008 }
2009
2010 // Parses simple list:
2011 // simple-variable-list:
2012 // '(' id-expression {, id-expression} ')'
2013 //
ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,const llvm::function_ref<void (CXXScopeSpec &,DeclarationNameInfo)> & Callback,bool AllowScopeSpecifier)2014 bool Parser::ParseOpenMPSimpleVarList(
2015 OpenMPDirectiveKind Kind,
2016 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
2017 Callback,
2018 bool AllowScopeSpecifier) {
2019 // Parse '('.
2020 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2021 if (T.expectAndConsume(diag::err_expected_lparen_after,
2022 getOpenMPDirectiveName(Kind).data()))
2023 return true;
2024 bool IsCorrect = true;
2025 bool NoIdentIsFound = true;
2026
2027 // Read tokens while ')' or annot_pragma_openmp_end is not found.
2028 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
2029 CXXScopeSpec SS;
2030 UnqualifiedId Name;
2031 // Read var name.
2032 Token PrevTok = Tok;
2033 NoIdentIsFound = false;
2034
2035 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2036 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
2037 IsCorrect = false;
2038 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2039 StopBeforeMatch);
2040 } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
2041 nullptr, Name)) {
2042 IsCorrect = false;
2043 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2044 StopBeforeMatch);
2045 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
2046 Tok.isNot(tok::annot_pragma_openmp_end)) {
2047 IsCorrect = false;
2048 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2049 StopBeforeMatch);
2050 Diag(PrevTok.getLocation(), diag::err_expected)
2051 << tok::identifier
2052 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2053 } else {
2054 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2055 }
2056 // Consume ','.
2057 if (Tok.is(tok::comma)) {
2058 ConsumeToken();
2059 }
2060 }
2061
2062 if (NoIdentIsFound) {
2063 Diag(Tok, diag::err_expected) << tok::identifier;
2064 IsCorrect = false;
2065 }
2066
2067 // Parse ')'.
2068 IsCorrect = !T.consumeClose() && IsCorrect;
2069
2070 return !IsCorrect;
2071 }
2072
2073 /// Parsing of OpenMP clauses.
2074 ///
2075 /// clause:
2076 /// if-clause | final-clause | num_threads-clause | safelen-clause |
2077 /// default-clause | private-clause | firstprivate-clause | shared-clause
2078 /// | linear-clause | aligned-clause | collapse-clause |
2079 /// lastprivate-clause | reduction-clause | proc_bind-clause |
2080 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
2081 /// mergeable-clause | flush-clause | read-clause | write-clause |
2082 /// update-clause | capture-clause | seq_cst-clause | device-clause |
2083 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
2084 /// thread_limit-clause | priority-clause | grainsize-clause |
2085 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
2086 /// from-clause | is_device_ptr-clause | task_reduction-clause |
2087 /// in_reduction-clause | allocator-clause | allocate-clause
2088 ///
ParseOpenMPClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,bool FirstClause)2089 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
2090 OpenMPClauseKind CKind, bool FirstClause) {
2091 OMPClause *Clause = nullptr;
2092 bool ErrorFound = false;
2093 bool WrongDirective = false;
2094 // Check if clause is allowed for the given directive.
2095 if (CKind != OMPC_unknown &&
2096 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
2097 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
2098 << getOpenMPDirectiveName(DKind);
2099 ErrorFound = true;
2100 WrongDirective = true;
2101 }
2102
2103 switch (CKind) {
2104 case OMPC_final:
2105 case OMPC_num_threads:
2106 case OMPC_safelen:
2107 case OMPC_simdlen:
2108 case OMPC_collapse:
2109 case OMPC_ordered:
2110 case OMPC_device:
2111 case OMPC_num_teams:
2112 case OMPC_thread_limit:
2113 case OMPC_priority:
2114 case OMPC_grainsize:
2115 case OMPC_num_tasks:
2116 case OMPC_hint:
2117 case OMPC_allocator:
2118 // OpenMP [2.5, Restrictions]
2119 // At most one num_threads clause can appear on the directive.
2120 // OpenMP [2.8.1, simd construct, Restrictions]
2121 // Only one safelen clause can appear on a simd directive.
2122 // Only one simdlen clause can appear on a simd directive.
2123 // Only one collapse clause can appear on a simd directive.
2124 // OpenMP [2.9.1, target data construct, Restrictions]
2125 // At most one device clause can appear on the directive.
2126 // OpenMP [2.11.1, task Construct, Restrictions]
2127 // At most one if clause can appear on the directive.
2128 // At most one final clause can appear on the directive.
2129 // OpenMP [teams Construct, Restrictions]
2130 // At most one num_teams clause can appear on the directive.
2131 // At most one thread_limit clause can appear on the directive.
2132 // OpenMP [2.9.1, task Construct, Restrictions]
2133 // At most one priority clause can appear on the directive.
2134 // OpenMP [2.9.2, taskloop Construct, Restrictions]
2135 // At most one grainsize clause can appear on the directive.
2136 // OpenMP [2.9.2, taskloop Construct, Restrictions]
2137 // At most one num_tasks clause can appear on the directive.
2138 // OpenMP [2.11.3, allocate Directive, Restrictions]
2139 // At most one allocator clause can appear on the directive.
2140 if (!FirstClause) {
2141 Diag(Tok, diag::err_omp_more_one_clause)
2142 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2143 ErrorFound = true;
2144 }
2145
2146 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
2147 Clause = ParseOpenMPClause(CKind, WrongDirective);
2148 else
2149 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
2150 break;
2151 case OMPC_default:
2152 case OMPC_proc_bind:
2153 case OMPC_atomic_default_mem_order:
2154 // OpenMP [2.14.3.1, Restrictions]
2155 // Only a single default clause may be specified on a parallel, task or
2156 // teams directive.
2157 // OpenMP [2.5, parallel Construct, Restrictions]
2158 // At most one proc_bind clause can appear on the directive.
2159 // OpenMP [5.0, Requires directive, Restrictions]
2160 // At most one atomic_default_mem_order clause can appear
2161 // on the directive
2162 if (!FirstClause) {
2163 Diag(Tok, diag::err_omp_more_one_clause)
2164 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2165 ErrorFound = true;
2166 }
2167
2168 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
2169 break;
2170 case OMPC_schedule:
2171 case OMPC_dist_schedule:
2172 case OMPC_defaultmap:
2173 // OpenMP [2.7.1, Restrictions, p. 3]
2174 // Only one schedule clause can appear on a loop directive.
2175 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
2176 // At most one defaultmap clause can appear on the directive.
2177 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
2178 !FirstClause) {
2179 Diag(Tok, diag::err_omp_more_one_clause)
2180 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2181 ErrorFound = true;
2182 }
2183 LLVM_FALLTHROUGH;
2184 case OMPC_if:
2185 Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
2186 break;
2187 case OMPC_nowait:
2188 case OMPC_untied:
2189 case OMPC_mergeable:
2190 case OMPC_read:
2191 case OMPC_write:
2192 case OMPC_update:
2193 case OMPC_capture:
2194 case OMPC_seq_cst:
2195 case OMPC_threads:
2196 case OMPC_simd:
2197 case OMPC_nogroup:
2198 case OMPC_unified_address:
2199 case OMPC_unified_shared_memory:
2200 case OMPC_reverse_offload:
2201 case OMPC_dynamic_allocators:
2202 // OpenMP [2.7.1, Restrictions, p. 9]
2203 // Only one ordered clause can appear on a loop directive.
2204 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
2205 // Only one nowait clause can appear on a for directive.
2206 // OpenMP [5.0, Requires directive, Restrictions]
2207 // Each of the requires clauses can appear at most once on the directive.
2208 if (!FirstClause) {
2209 Diag(Tok, diag::err_omp_more_one_clause)
2210 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2211 ErrorFound = true;
2212 }
2213
2214 Clause = ParseOpenMPClause(CKind, WrongDirective);
2215 break;
2216 case OMPC_private:
2217 case OMPC_firstprivate:
2218 case OMPC_lastprivate:
2219 case OMPC_shared:
2220 case OMPC_reduction:
2221 case OMPC_task_reduction:
2222 case OMPC_in_reduction:
2223 case OMPC_linear:
2224 case OMPC_aligned:
2225 case OMPC_copyin:
2226 case OMPC_copyprivate:
2227 case OMPC_flush:
2228 case OMPC_depend:
2229 case OMPC_map:
2230 case OMPC_to:
2231 case OMPC_from:
2232 case OMPC_use_device_ptr:
2233 case OMPC_is_device_ptr:
2234 case OMPC_allocate:
2235 case OMPC_nontemporal:
2236 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
2237 break;
2238 case OMPC_device_type:
2239 case OMPC_unknown:
2240 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
2241 << getOpenMPDirectiveName(DKind);
2242 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
2243 break;
2244 case OMPC_threadprivate:
2245 case OMPC_uniform:
2246 case OMPC_match:
2247 if (!WrongDirective)
2248 Diag(Tok, diag::err_omp_unexpected_clause)
2249 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
2250 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
2251 break;
2252 }
2253 return ErrorFound ? nullptr : Clause;
2254 }
2255
2256 /// Parses simple expression in parens for single-expression clauses of OpenMP
2257 /// constructs.
2258 /// \param RLoc Returned location of right paren.
ParseOpenMPParensExpr(StringRef ClauseName,SourceLocation & RLoc,bool IsAddressOfOperand)2259 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
2260 SourceLocation &RLoc,
2261 bool IsAddressOfOperand) {
2262 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2263 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
2264 return ExprError();
2265
2266 SourceLocation ELoc = Tok.getLocation();
2267 ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand,
2268 NotTypeCast));
2269 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
2270 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2271
2272 // Parse ')'.
2273 RLoc = Tok.getLocation();
2274 if (!T.consumeClose())
2275 RLoc = T.getCloseLocation();
2276
2277 return Val;
2278 }
2279
2280 /// Parsing of OpenMP clauses with single expressions like 'final',
2281 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
2282 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
2283 ///
2284 /// final-clause:
2285 /// 'final' '(' expression ')'
2286 ///
2287 /// num_threads-clause:
2288 /// 'num_threads' '(' expression ')'
2289 ///
2290 /// safelen-clause:
2291 /// 'safelen' '(' expression ')'
2292 ///
2293 /// simdlen-clause:
2294 /// 'simdlen' '(' expression ')'
2295 ///
2296 /// collapse-clause:
2297 /// 'collapse' '(' expression ')'
2298 ///
2299 /// priority-clause:
2300 /// 'priority' '(' expression ')'
2301 ///
2302 /// grainsize-clause:
2303 /// 'grainsize' '(' expression ')'
2304 ///
2305 /// num_tasks-clause:
2306 /// 'num_tasks' '(' expression ')'
2307 ///
2308 /// hint-clause:
2309 /// 'hint' '(' expression ')'
2310 ///
2311 /// allocator-clause:
2312 /// 'allocator' '(' expression ')'
2313 ///
ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,bool ParseOnly)2314 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
2315 bool ParseOnly) {
2316 SourceLocation Loc = ConsumeToken();
2317 SourceLocation LLoc = Tok.getLocation();
2318 SourceLocation RLoc;
2319
2320 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
2321
2322 if (Val.isInvalid())
2323 return nullptr;
2324
2325 if (ParseOnly)
2326 return nullptr;
2327 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
2328 }
2329
2330 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
2331 ///
2332 /// default-clause:
2333 /// 'default' '(' 'none' | 'shared' ')
2334 ///
2335 /// proc_bind-clause:
2336 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
2337 ///
ParseOpenMPSimpleClause(OpenMPClauseKind Kind,bool ParseOnly)2338 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
2339 bool ParseOnly) {
2340 llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
2341 if (!Val || ParseOnly)
2342 return nullptr;
2343 return Actions.ActOnOpenMPSimpleClause(
2344 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
2345 Val.getValue().Loc, Val.getValue().RLoc);
2346 }
2347
2348 /// Parsing of OpenMP clauses like 'ordered'.
2349 ///
2350 /// ordered-clause:
2351 /// 'ordered'
2352 ///
2353 /// nowait-clause:
2354 /// 'nowait'
2355 ///
2356 /// untied-clause:
2357 /// 'untied'
2358 ///
2359 /// mergeable-clause:
2360 /// 'mergeable'
2361 ///
2362 /// read-clause:
2363 /// 'read'
2364 ///
2365 /// threads-clause:
2366 /// 'threads'
2367 ///
2368 /// simd-clause:
2369 /// 'simd'
2370 ///
2371 /// nogroup-clause:
2372 /// 'nogroup'
2373 ///
ParseOpenMPClause(OpenMPClauseKind Kind,bool ParseOnly)2374 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
2375 SourceLocation Loc = Tok.getLocation();
2376 ConsumeAnyToken();
2377
2378 if (ParseOnly)
2379 return nullptr;
2380 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
2381 }
2382
2383
2384 /// Parsing of OpenMP clauses with single expressions and some additional
2385 /// argument like 'schedule' or 'dist_schedule'.
2386 ///
2387 /// schedule-clause:
2388 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
2389 /// ')'
2390 ///
2391 /// if-clause:
2392 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
2393 ///
2394 /// defaultmap:
2395 /// 'defaultmap' '(' modifier ':' kind ')'
2396 ///
ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,bool ParseOnly)2397 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
2398 bool ParseOnly) {
2399 SourceLocation Loc = ConsumeToken();
2400 SourceLocation DelimLoc;
2401 // Parse '('.
2402 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2403 if (T.expectAndConsume(diag::err_expected_lparen_after,
2404 getOpenMPClauseName(Kind)))
2405 return nullptr;
2406
2407 ExprResult Val;
2408 SmallVector<unsigned, 4> Arg;
2409 SmallVector<SourceLocation, 4> KLoc;
2410 if (Kind == OMPC_schedule) {
2411 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
2412 Arg.resize(NumberOfElements);
2413 KLoc.resize(NumberOfElements);
2414 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
2415 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
2416 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
2417 unsigned KindModifier = getOpenMPSimpleClauseType(
2418 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2419 if (KindModifier > OMPC_SCHEDULE_unknown) {
2420 // Parse 'modifier'
2421 Arg[Modifier1] = KindModifier;
2422 KLoc[Modifier1] = Tok.getLocation();
2423 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2424 Tok.isNot(tok::annot_pragma_openmp_end))
2425 ConsumeAnyToken();
2426 if (Tok.is(tok::comma)) {
2427 // Parse ',' 'modifier'
2428 ConsumeAnyToken();
2429 KindModifier = getOpenMPSimpleClauseType(
2430 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2431 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
2432 ? KindModifier
2433 : (unsigned)OMPC_SCHEDULE_unknown;
2434 KLoc[Modifier2] = Tok.getLocation();
2435 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2436 Tok.isNot(tok::annot_pragma_openmp_end))
2437 ConsumeAnyToken();
2438 }
2439 // Parse ':'
2440 if (Tok.is(tok::colon))
2441 ConsumeAnyToken();
2442 else
2443 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
2444 KindModifier = getOpenMPSimpleClauseType(
2445 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2446 }
2447 Arg[ScheduleKind] = KindModifier;
2448 KLoc[ScheduleKind] = Tok.getLocation();
2449 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2450 Tok.isNot(tok::annot_pragma_openmp_end))
2451 ConsumeAnyToken();
2452 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
2453 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
2454 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
2455 Tok.is(tok::comma))
2456 DelimLoc = ConsumeAnyToken();
2457 } else if (Kind == OMPC_dist_schedule) {
2458 Arg.push_back(getOpenMPSimpleClauseType(
2459 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
2460 KLoc.push_back(Tok.getLocation());
2461 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2462 Tok.isNot(tok::annot_pragma_openmp_end))
2463 ConsumeAnyToken();
2464 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
2465 DelimLoc = ConsumeAnyToken();
2466 } else if (Kind == OMPC_defaultmap) {
2467 // Get a defaultmap modifier
2468 unsigned Modifier = getOpenMPSimpleClauseType(
2469 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
2470 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
2471 // pointer
2472 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
2473 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
2474 Arg.push_back(Modifier);
2475 KLoc.push_back(Tok.getLocation());
2476 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2477 Tok.isNot(tok::annot_pragma_openmp_end))
2478 ConsumeAnyToken();
2479 // Parse ':'
2480 if (Tok.is(tok::colon))
2481 ConsumeAnyToken();
2482 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
2483 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
2484 // Get a defaultmap kind
2485 Arg.push_back(getOpenMPSimpleClauseType(
2486 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
2487 KLoc.push_back(Tok.getLocation());
2488 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2489 Tok.isNot(tok::annot_pragma_openmp_end))
2490 ConsumeAnyToken();
2491 } else {
2492 assert(Kind == OMPC_if);
2493 KLoc.push_back(Tok.getLocation());
2494 TentativeParsingAction TPA(*this);
2495 auto DK = parseOpenMPDirectiveKind(*this);
2496 Arg.push_back(DK);
2497 if (DK != OMPD_unknown) {
2498 ConsumeToken();
2499 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
2500 TPA.Commit();
2501 DelimLoc = ConsumeToken();
2502 } else {
2503 TPA.Revert();
2504 Arg.back() = unsigned(OMPD_unknown);
2505 }
2506 } else {
2507 TPA.Revert();
2508 }
2509 }
2510
2511 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
2512 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
2513 Kind == OMPC_if;
2514 if (NeedAnExpression) {
2515 SourceLocation ELoc = Tok.getLocation();
2516 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
2517 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
2518 Val =
2519 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2520 }
2521
2522 // Parse ')'.
2523 SourceLocation RLoc = Tok.getLocation();
2524 if (!T.consumeClose())
2525 RLoc = T.getCloseLocation();
2526
2527 if (NeedAnExpression && Val.isInvalid())
2528 return nullptr;
2529
2530 if (ParseOnly)
2531 return nullptr;
2532 return Actions.ActOnOpenMPSingleExprWithArgClause(
2533 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
2534 }
2535
ParseReductionId(Parser & P,CXXScopeSpec & ReductionIdScopeSpec,UnqualifiedId & ReductionId)2536 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
2537 UnqualifiedId &ReductionId) {
2538 if (ReductionIdScopeSpec.isEmpty()) {
2539 auto OOK = OO_None;
2540 switch (P.getCurToken().getKind()) {
2541 case tok::plus:
2542 OOK = OO_Plus;
2543 break;
2544 case tok::minus:
2545 OOK = OO_Minus;
2546 break;
2547 case tok::star:
2548 OOK = OO_Star;
2549 break;
2550 case tok::amp:
2551 OOK = OO_Amp;
2552 break;
2553 case tok::pipe:
2554 OOK = OO_Pipe;
2555 break;
2556 case tok::caret:
2557 OOK = OO_Caret;
2558 break;
2559 case tok::ampamp:
2560 OOK = OO_AmpAmp;
2561 break;
2562 case tok::pipepipe:
2563 OOK = OO_PipePipe;
2564 break;
2565 default:
2566 break;
2567 }
2568 if (OOK != OO_None) {
2569 SourceLocation OpLoc = P.ConsumeToken();
2570 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
2571 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
2572 return false;
2573 }
2574 }
2575 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
2576 /*AllowDestructorName*/ false,
2577 /*AllowConstructorName*/ false,
2578 /*AllowDeductionGuide*/ false,
2579 nullptr, nullptr, ReductionId);
2580 }
2581
2582 /// Checks if the token is a valid map-type-modifier.
isMapModifier(Parser & P)2583 static OpenMPMapModifierKind isMapModifier(Parser &P) {
2584 Token Tok = P.getCurToken();
2585 if (!Tok.is(tok::identifier))
2586 return OMPC_MAP_MODIFIER_unknown;
2587
2588 Preprocessor &PP = P.getPreprocessor();
2589 OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
2590 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2591 return TypeModifier;
2592 }
2593
2594 /// Parse the mapper modifier in map, to, and from clauses.
parseMapperModifier(OpenMPVarListDataTy & Data)2595 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
2596 // Parse '('.
2597 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
2598 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
2599 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2600 StopBeforeMatch);
2601 return true;
2602 }
2603 // Parse mapper-identifier
2604 if (getLangOpts().CPlusPlus)
2605 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2606 /*ObjectType=*/nullptr,
2607 /*EnteringContext=*/false);
2608 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
2609 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
2610 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2611 StopBeforeMatch);
2612 return true;
2613 }
2614 auto &DeclNames = Actions.getASTContext().DeclarationNames;
2615 Data.ReductionOrMapperId = DeclarationNameInfo(
2616 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
2617 ConsumeToken();
2618 // Parse ')'.
2619 return T.consumeClose();
2620 }
2621
2622 /// Parse map-type-modifiers in map clause.
2623 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2624 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
parseMapTypeModifiers(OpenMPVarListDataTy & Data)2625 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
2626 while (getCurToken().isNot(tok::colon)) {
2627 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
2628 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
2629 TypeModifier == OMPC_MAP_MODIFIER_close) {
2630 Data.MapTypeModifiers.push_back(TypeModifier);
2631 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2632 ConsumeToken();
2633 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
2634 Data.MapTypeModifiers.push_back(TypeModifier);
2635 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2636 ConsumeToken();
2637 if (parseMapperModifier(Data))
2638 return true;
2639 } else {
2640 // For the case of unknown map-type-modifier or a map-type.
2641 // Map-type is followed by a colon; the function returns when it
2642 // encounters a token followed by a colon.
2643 if (Tok.is(tok::comma)) {
2644 Diag(Tok, diag::err_omp_map_type_modifier_missing);
2645 ConsumeToken();
2646 continue;
2647 }
2648 // Potential map-type token as it is followed by a colon.
2649 if (PP.LookAhead(0).is(tok::colon))
2650 return false;
2651 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
2652 ConsumeToken();
2653 }
2654 if (getCurToken().is(tok::comma))
2655 ConsumeToken();
2656 }
2657 return false;
2658 }
2659
2660 /// Checks if the token is a valid map-type.
isMapType(Parser & P)2661 static OpenMPMapClauseKind isMapType(Parser &P) {
2662 Token Tok = P.getCurToken();
2663 // The map-type token can be either an identifier or the C++ delete keyword.
2664 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
2665 return OMPC_MAP_unknown;
2666 Preprocessor &PP = P.getPreprocessor();
2667 OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
2668 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2669 return MapType;
2670 }
2671
2672 /// Parse map-type in map clause.
2673 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2674 /// where, map-type ::= to | from | tofrom | alloc | release | delete
parseMapType(Parser & P,Parser::OpenMPVarListDataTy & Data)2675 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
2676 Token Tok = P.getCurToken();
2677 if (Tok.is(tok::colon)) {
2678 P.Diag(Tok, diag::err_omp_map_type_missing);
2679 return;
2680 }
2681 Data.ExtraModifier = isMapType(P);
2682 if (Data.ExtraModifier == OMPC_MAP_unknown)
2683 P.Diag(Tok, diag::err_omp_unknown_map_type);
2684 P.ConsumeToken();
2685 }
2686
2687 /// Parses clauses with list.
ParseOpenMPVarList(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,SmallVectorImpl<Expr * > & Vars,OpenMPVarListDataTy & Data)2688 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
2689 OpenMPClauseKind Kind,
2690 SmallVectorImpl<Expr *> &Vars,
2691 OpenMPVarListDataTy &Data) {
2692 UnqualifiedId UnqualifiedReductionId;
2693 bool InvalidReductionId = false;
2694 bool IsInvalidMapperModifier = false;
2695
2696 // Parse '('.
2697 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2698 if (T.expectAndConsume(diag::err_expected_lparen_after,
2699 getOpenMPClauseName(Kind)))
2700 return true;
2701
2702 bool NeedRParenForLinear = false;
2703 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
2704 tok::annot_pragma_openmp_end);
2705 // Handle reduction-identifier for reduction clause.
2706 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
2707 Kind == OMPC_in_reduction) {
2708 ColonProtectionRAIIObject ColonRAII(*this);
2709 if (getLangOpts().CPlusPlus)
2710 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2711 /*ObjectType=*/nullptr,
2712 /*EnteringContext=*/false);
2713 InvalidReductionId = ParseReductionId(
2714 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
2715 if (InvalidReductionId) {
2716 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2717 StopBeforeMatch);
2718 }
2719 if (Tok.is(tok::colon))
2720 Data.ColonLoc = ConsumeToken();
2721 else
2722 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
2723 if (!InvalidReductionId)
2724 Data.ReductionOrMapperId =
2725 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
2726 } else if (Kind == OMPC_depend) {
2727 // Handle dependency type for depend clause.
2728 ColonProtectionRAIIObject ColonRAII(*this);
2729 Data.ExtraModifier = getOpenMPSimpleClauseType(
2730 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "");
2731 Data.DepLinMapLastLoc = Tok.getLocation();
2732 if (Data.ExtraModifier == OMPC_DEPEND_unknown) {
2733 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2734 StopBeforeMatch);
2735 } else {
2736 ConsumeToken();
2737 // Special processing for depend(source) clause.
2738 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) {
2739 // Parse ')'.
2740 T.consumeClose();
2741 return false;
2742 }
2743 }
2744 if (Tok.is(tok::colon)) {
2745 Data.ColonLoc = ConsumeToken();
2746 } else {
2747 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
2748 : diag::warn_pragma_expected_colon)
2749 << "dependency type";
2750 }
2751 } else if (Kind == OMPC_linear) {
2752 // Try to parse modifier if any.
2753 Data.ExtraModifier = OMPC_LINEAR_val;
2754 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
2755 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
2756 Data.DepLinMapLastLoc = ConsumeToken();
2757 LinearT.consumeOpen();
2758 NeedRParenForLinear = true;
2759 }
2760 } else if (Kind == OMPC_lastprivate) {
2761 // Try to parse modifier if any.
2762 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
2763 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
2764 // distribute and taskloop based directives.
2765 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
2766 !isOpenMPTaskLoopDirective(DKind)) &&
2767 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
2768 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
2769 Data.DepLinMapLastLoc = Tok.getLocation();
2770 if (Data.ExtraModifier == OMPC_LASTPRIVATE_unknown) {
2771 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2772 StopBeforeMatch);
2773 } else {
2774 ConsumeToken();
2775 }
2776 assert(Tok.is(tok::colon) && "Expected colon.");
2777 Data.ColonLoc = ConsumeToken();
2778 }
2779 } else if (Kind == OMPC_map) {
2780 // Handle map type for map clause.
2781 ColonProtectionRAIIObject ColonRAII(*this);
2782
2783 // The first identifier may be a list item, a map-type or a
2784 // map-type-modifier. The map-type can also be delete which has the same
2785 // spelling of the C++ delete keyword.
2786 Data.ExtraModifier = OMPC_MAP_unknown;
2787 Data.DepLinMapLastLoc = Tok.getLocation();
2788
2789 // Check for presence of a colon in the map clause.
2790 TentativeParsingAction TPA(*this);
2791 bool ColonPresent = false;
2792 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2793 StopBeforeMatch)) {
2794 if (Tok.is(tok::colon))
2795 ColonPresent = true;
2796 }
2797 TPA.Revert();
2798 // Only parse map-type-modifier[s] and map-type if a colon is present in
2799 // the map clause.
2800 if (ColonPresent) {
2801 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
2802 if (!IsInvalidMapperModifier)
2803 parseMapType(*this, Data);
2804 else
2805 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
2806 }
2807 if (Data.ExtraModifier == OMPC_MAP_unknown) {
2808 Data.ExtraModifier = OMPC_MAP_tofrom;
2809 Data.IsMapTypeImplicit = true;
2810 }
2811
2812 if (Tok.is(tok::colon))
2813 Data.ColonLoc = ConsumeToken();
2814 } else if (Kind == OMPC_to || Kind == OMPC_from) {
2815 if (Tok.is(tok::identifier)) {
2816 bool IsMapperModifier = false;
2817 if (Kind == OMPC_to) {
2818 auto Modifier = static_cast<OpenMPToModifierKind>(
2819 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2820 if (Modifier == OMPC_TO_MODIFIER_mapper)
2821 IsMapperModifier = true;
2822 } else {
2823 auto Modifier = static_cast<OpenMPFromModifierKind>(
2824 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2825 if (Modifier == OMPC_FROM_MODIFIER_mapper)
2826 IsMapperModifier = true;
2827 }
2828 if (IsMapperModifier) {
2829 // Parse the mapper modifier.
2830 ConsumeToken();
2831 IsInvalidMapperModifier = parseMapperModifier(Data);
2832 if (Tok.isNot(tok::colon)) {
2833 if (!IsInvalidMapperModifier)
2834 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
2835 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2836 StopBeforeMatch);
2837 }
2838 // Consume ':'.
2839 if (Tok.is(tok::colon))
2840 ConsumeToken();
2841 }
2842 }
2843 } else if (Kind == OMPC_allocate) {
2844 // Handle optional allocator expression followed by colon delimiter.
2845 ColonProtectionRAIIObject ColonRAII(*this);
2846 TentativeParsingAction TPA(*this);
2847 ExprResult Tail =
2848 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2849 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
2850 /*DiscardedValue=*/false);
2851 if (Tail.isUsable()) {
2852 if (Tok.is(tok::colon)) {
2853 Data.TailExpr = Tail.get();
2854 Data.ColonLoc = ConsumeToken();
2855 TPA.Commit();
2856 } else {
2857 // colon not found, no allocator specified, parse only list of
2858 // variables.
2859 TPA.Revert();
2860 }
2861 } else {
2862 // Parsing was unsuccessfull, revert and skip to the end of clause or
2863 // directive.
2864 TPA.Revert();
2865 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2866 StopBeforeMatch);
2867 }
2868 }
2869
2870 bool IsComma =
2871 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
2872 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
2873 (Kind == OMPC_reduction && !InvalidReductionId) ||
2874 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
2875 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
2876 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
2877 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
2878 Tok.isNot(tok::annot_pragma_openmp_end))) {
2879 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
2880 // Parse variable
2881 ExprResult VarExpr =
2882 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2883 if (VarExpr.isUsable()) {
2884 Vars.push_back(VarExpr.get());
2885 } else {
2886 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2887 StopBeforeMatch);
2888 }
2889 // Skip ',' if any
2890 IsComma = Tok.is(tok::comma);
2891 if (IsComma)
2892 ConsumeToken();
2893 else if (Tok.isNot(tok::r_paren) &&
2894 Tok.isNot(tok::annot_pragma_openmp_end) &&
2895 (!MayHaveTail || Tok.isNot(tok::colon)))
2896 Diag(Tok, diag::err_omp_expected_punc)
2897 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
2898 : getOpenMPClauseName(Kind))
2899 << (Kind == OMPC_flush);
2900 }
2901
2902 // Parse ')' for linear clause with modifier.
2903 if (NeedRParenForLinear)
2904 LinearT.consumeClose();
2905
2906 // Parse ':' linear-step (or ':' alignment).
2907 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
2908 if (MustHaveTail) {
2909 Data.ColonLoc = Tok.getLocation();
2910 SourceLocation ELoc = ConsumeToken();
2911 ExprResult Tail = ParseAssignmentExpression();
2912 Tail =
2913 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
2914 if (Tail.isUsable())
2915 Data.TailExpr = Tail.get();
2916 else
2917 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2918 StopBeforeMatch);
2919 }
2920
2921 // Parse ')'.
2922 Data.RLoc = Tok.getLocation();
2923 if (!T.consumeClose())
2924 Data.RLoc = T.getCloseLocation();
2925 return (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown &&
2926 Vars.empty()) ||
2927 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
2928 (MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
2929 IsInvalidMapperModifier;
2930 }
2931
2932 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
2933 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
2934 /// 'in_reduction'.
2935 ///
2936 /// private-clause:
2937 /// 'private' '(' list ')'
2938 /// firstprivate-clause:
2939 /// 'firstprivate' '(' list ')'
2940 /// lastprivate-clause:
2941 /// 'lastprivate' '(' list ')'
2942 /// shared-clause:
2943 /// 'shared' '(' list ')'
2944 /// linear-clause:
2945 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
2946 /// aligned-clause:
2947 /// 'aligned' '(' list [ ':' alignment ] ')'
2948 /// reduction-clause:
2949 /// 'reduction' '(' reduction-identifier ':' list ')'
2950 /// task_reduction-clause:
2951 /// 'task_reduction' '(' reduction-identifier ':' list ')'
2952 /// in_reduction-clause:
2953 /// 'in_reduction' '(' reduction-identifier ':' list ')'
2954 /// copyprivate-clause:
2955 /// 'copyprivate' '(' list ')'
2956 /// flush-clause:
2957 /// 'flush' '(' list ')'
2958 /// depend-clause:
2959 /// 'depend' '(' in | out | inout : list | source ')'
2960 /// map-clause:
2961 /// 'map' '(' [ [ always [,] ] [ close [,] ]
2962 /// [ mapper '(' mapper-identifier ')' [,] ]
2963 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
2964 /// to-clause:
2965 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2966 /// from-clause:
2967 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2968 /// use_device_ptr-clause:
2969 /// 'use_device_ptr' '(' list ')'
2970 /// is_device_ptr-clause:
2971 /// 'is_device_ptr' '(' list ')'
2972 /// allocate-clause:
2973 /// 'allocate' '(' [ allocator ':' ] list ')'
2974 ///
2975 /// For 'linear' clause linear-list may have the following forms:
2976 /// list
2977 /// modifier(list)
2978 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,bool ParseOnly)2979 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
2980 OpenMPClauseKind Kind,
2981 bool ParseOnly) {
2982 SourceLocation Loc = Tok.getLocation();
2983 SourceLocation LOpen = ConsumeToken();
2984 SmallVector<Expr *, 4> Vars;
2985 OpenMPVarListDataTy Data;
2986
2987 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
2988 return nullptr;
2989
2990 if (ParseOnly)
2991 return nullptr;
2992 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
2993 return Actions.ActOnOpenMPVarListClause(
2994 Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
2995 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
2996 Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
2997 Data.IsMapTypeImplicit, Data.DepLinMapLastLoc);
2998 }
2999
3000