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