clang 20.0.0git
ParseOpenMP.cpp
Go to the documentation of this file.
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
20#include "clang/Parse/Parser.h"
23#include "clang/Sema/Scope.h"
27#include "llvm/ADT/SmallBitVector.h"
28#include "llvm/ADT/StringSwitch.h"
29#include "llvm/Frontend/OpenMP/OMPAssume.h"
30#include "llvm/Frontend/OpenMP/OMPContext.h"
31#include <optional>
32
33using namespace clang;
34using namespace llvm::omp;
35
36//===----------------------------------------------------------------------===//
37// OpenMP declarative directives.
38//===----------------------------------------------------------------------===//
39
40namespace {
41enum OpenMPDirectiveKindEx {
42 OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
43 OMPD_data,
44 OMPD_declare,
45 OMPD_end,
46 OMPD_end_declare,
47 OMPD_enter,
48 OMPD_exit,
49 OMPD_point,
50 OMPD_reduction,
51 OMPD_target_enter,
52 OMPD_target_exit,
53 OMPD_update,
54 OMPD_distribute_parallel,
55 OMPD_teams_distribute_parallel,
56 OMPD_target_teams_distribute_parallel,
57 OMPD_mapper,
58 OMPD_variant,
59 OMPD_begin,
60 OMPD_begin_declare,
61};
62
63// Helper to unify the enum class OpenMPDirectiveKind with its extension
64// the OpenMPDirectiveKindEx enum which allows to use them together as if they
65// are unsigned values.
66struct OpenMPDirectiveKindExWrapper {
67 OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
68 OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
69 bool operator==(OpenMPDirectiveKindExWrapper V) const {
70 return Value == V.Value;
71 }
72 bool operator!=(OpenMPDirectiveKindExWrapper V) const {
73 return Value != V.Value;
74 }
75 bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
76 bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
77 bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
78 operator unsigned() const { return Value; }
79 operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
80 unsigned Value;
81};
82
83class DeclDirectiveListParserHelper final {
84 SmallVector<Expr *, 4> Identifiers;
85 Parser *P;
87
88public:
89 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
90 : P(P), Kind(Kind) {}
91 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
92 ExprResult Res = P->getActions().OpenMP().ActOnOpenMPIdExpression(
93 P->getCurScope(), SS, NameInfo, Kind);
94 if (Res.isUsable())
95 Identifiers.push_back(Res.get());
96 }
97 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
98};
99} // namespace
100
101// Map token string to extended OMP token kind that are
102// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
103static unsigned getOpenMPDirectiveKindEx(StringRef S) {
104 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
105 if (DKind != OMPD_unknown)
106 return DKind;
107
108 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
109 .Case("cancellation", OMPD_cancellation)
110 .Case("data", OMPD_data)
111 .Case("declare", OMPD_declare)
112 .Case("end", OMPD_end)
113 .Case("enter", OMPD_enter)
114 .Case("exit", OMPD_exit)
115 .Case("point", OMPD_point)
116 .Case("reduction", OMPD_reduction)
117 .Case("update", OMPD_update)
118 .Case("mapper", OMPD_mapper)
119 .Case("variant", OMPD_variant)
120 .Case("begin", OMPD_begin)
121 .Default(OMPD_unknown);
122}
123
124static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
125 // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
126 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
127 // TODO: add other combined directives in topological order.
128 static const OpenMPDirectiveKindExWrapper F[][3] = {
129 {OMPD_begin, OMPD_declare, OMPD_begin_declare},
130 {OMPD_begin, OMPD_assumes, OMPD_begin_assumes},
131 {OMPD_end, OMPD_declare, OMPD_end_declare},
132 {OMPD_end, OMPD_assumes, OMPD_end_assumes},
133 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
134 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
135 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
136 {OMPD_declare, OMPD_simd, OMPD_declare_simd},
137 {OMPD_declare, OMPD_target, OMPD_declare_target},
138 {OMPD_declare, OMPD_variant, OMPD_declare_variant},
139 {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
140 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
141 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
142 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
143 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
144 {OMPD_distribute_parallel_for, OMPD_simd,
145 OMPD_distribute_parallel_for_simd},
146 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
147 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
148 {OMPD_target, OMPD_data, OMPD_target_data},
149 {OMPD_target, OMPD_enter, OMPD_target_enter},
150 {OMPD_target, OMPD_exit, OMPD_target_exit},
151 {OMPD_target, OMPD_update, OMPD_target_update},
152 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
153 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
154 {OMPD_for, OMPD_simd, OMPD_for_simd},
155 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
156 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
157 {OMPD_parallel, OMPD_loop, OMPD_parallel_loop},
158 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
159 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
160 {OMPD_target, OMPD_parallel, OMPD_target_parallel},
161 {OMPD_target, OMPD_simd, OMPD_target_simd},
162 {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},
163 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
164 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
165 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
166 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
167 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
168 {OMPD_teams_distribute_parallel, OMPD_for,
169 OMPD_teams_distribute_parallel_for},
170 {OMPD_teams_distribute_parallel_for, OMPD_simd,
171 OMPD_teams_distribute_parallel_for_simd},
172 {OMPD_teams, OMPD_loop, OMPD_teams_loop},
173 {OMPD_target, OMPD_teams, OMPD_target_teams},
174 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
175 {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},
176 {OMPD_target_teams_distribute, OMPD_parallel,
177 OMPD_target_teams_distribute_parallel},
178 {OMPD_target_teams_distribute, OMPD_simd,
179 OMPD_target_teams_distribute_simd},
180 {OMPD_target_teams_distribute_parallel, OMPD_for,
181 OMPD_target_teams_distribute_parallel_for},
182 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
183 OMPD_target_teams_distribute_parallel_for_simd},
184 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
185 {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},
186 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
187 {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},
188 {OMPD_parallel, OMPD_master, OMPD_parallel_master},
189 {OMPD_parallel, OMPD_masked, OMPD_parallel_masked},
190 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
191 {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},
192 {OMPD_parallel_master_taskloop, OMPD_simd,
193 OMPD_parallel_master_taskloop_simd},
194 {OMPD_parallel_masked_taskloop, OMPD_simd,
195 OMPD_parallel_masked_taskloop_simd}};
196 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
197 Token Tok = P.getCurToken();
198 OpenMPDirectiveKindExWrapper DKind =
199 Tok.isAnnotation()
200 ? static_cast<unsigned>(OMPD_unknown)
201 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
202 if (DKind == OMPD_unknown)
203 return OMPD_unknown;
204
205 for (const auto &I : F) {
206 if (DKind != I[0])
207 continue;
208
209 Tok = P.getPreprocessor().LookAhead(0);
210 OpenMPDirectiveKindExWrapper SDKind =
211 Tok.isAnnotation()
212 ? static_cast<unsigned>(OMPD_unknown)
213 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
214 if (SDKind == OMPD_unknown)
215 continue;
216
217 if (SDKind == I[1]) {
218 P.ConsumeToken();
219 DKind = I[2];
220 }
221 }
222 return unsigned(DKind) < llvm::omp::Directive_enumSize
223 ? static_cast<OpenMPDirectiveKind>(DKind)
224 : OMPD_unknown;
225}
226
228 Token Tok = P.getCurToken();
229 Sema &Actions = P.getActions();
231 // Allow to use 'operator' keyword for C++ operators
232 bool WithOperator = false;
233 if (Tok.is(tok::kw_operator)) {
234 P.ConsumeToken();
235 Tok = P.getCurToken();
236 WithOperator = true;
237 }
238 switch (Tok.getKind()) {
239 case tok::plus: // '+'
240 OOK = OO_Plus;
241 break;
242 case tok::minus: // '-'
243 OOK = OO_Minus;
244 break;
245 case tok::star: // '*'
246 OOK = OO_Star;
247 break;
248 case tok::amp: // '&'
249 OOK = OO_Amp;
250 break;
251 case tok::pipe: // '|'
252 OOK = OO_Pipe;
253 break;
254 case tok::caret: // '^'
255 OOK = OO_Caret;
256 break;
257 case tok::ampamp: // '&&'
258 OOK = OO_AmpAmp;
259 break;
260 case tok::pipepipe: // '||'
261 OOK = OO_PipePipe;
262 break;
263 case tok::identifier: // identifier
264 if (!WithOperator)
265 break;
266 [[fallthrough]];
267 default:
268 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
269 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
271 return DeclarationName();
272 }
273 P.ConsumeToken();
274 auto &DeclNames = Actions.getASTContext().DeclarationNames;
275 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
276 : DeclNames.getCXXOperatorName(OOK);
277}
278
279/// Parse 'omp declare reduction' construct.
280///
281/// declare-reduction-directive:
282/// annot_pragma_openmp 'declare' 'reduction'
283/// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
284/// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
285/// annot_pragma_openmp_end
286/// <reduction_id> is either a base language identifier or one of the following
287/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
288///
290Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
291 // Parse '('.
292 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
293 if (T.expectAndConsume(
294 diag::err_expected_lparen_after,
295 getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
296 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
297 return DeclGroupPtrTy();
298 }
299
301 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
302 return DeclGroupPtrTy();
303
304 // Consume ':'.
305 bool IsCorrect = !ExpectAndConsume(tok::colon);
306
307 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
308 return DeclGroupPtrTy();
309
310 IsCorrect = IsCorrect && !Name.isEmpty();
311
312 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
313 Diag(Tok.getLocation(), diag::err_expected_type);
314 IsCorrect = false;
315 }
316
317 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
318 return DeclGroupPtrTy();
319
321 // Parse list of types until ':' token.
322 do {
323 ColonProtectionRAIIObject ColonRAII(*this);
326 if (TR.isUsable()) {
327 QualType ReductionType = Actions.OpenMP().ActOnOpenMPDeclareReductionType(
328 Range.getBegin(), TR);
329 if (!ReductionType.isNull()) {
330 ReductionTypes.push_back(
331 std::make_pair(ReductionType, Range.getBegin()));
332 }
333 } else {
334 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
336 }
337
338 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
339 break;
340
341 // Consume ','.
342 if (ExpectAndConsume(tok::comma)) {
343 IsCorrect = false;
344 if (Tok.is(tok::annot_pragma_openmp_end)) {
345 Diag(Tok.getLocation(), diag::err_expected_type);
346 return DeclGroupPtrTy();
347 }
348 }
349 } while (Tok.isNot(tok::annot_pragma_openmp_end));
350
351 if (ReductionTypes.empty()) {
352 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
353 return DeclGroupPtrTy();
354 }
355
356 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
357 return DeclGroupPtrTy();
358
359 // Consume ':'.
360 if (ExpectAndConsume(tok::colon))
361 IsCorrect = false;
362
363 if (Tok.is(tok::annot_pragma_openmp_end)) {
364 Diag(Tok.getLocation(), diag::err_expected_expression);
365 return DeclGroupPtrTy();
366 }
367
368 DeclGroupPtrTy DRD =
370 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes,
371 AS);
372
373 // Parse <combiner> expression and then parse initializer if any for each
374 // correct type.
375 unsigned I = 0, E = ReductionTypes.size();
376 for (Decl *D : DRD.get()) {
377 TentativeParsingAction TPA(*this);
378 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
381 // Parse <combiner> expression.
383 ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
384 ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
386 D, CombinerResult.get());
387
388 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
389 Tok.isNot(tok::annot_pragma_openmp_end)) {
390 TPA.Commit();
391 IsCorrect = false;
392 break;
393 }
394 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
395 ExprResult InitializerResult;
396 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
397 // Parse <initializer> expression.
398 if (Tok.is(tok::identifier) &&
399 Tok.getIdentifierInfo()->isStr("initializer")) {
400 ConsumeToken();
401 } else {
402 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
403 TPA.Commit();
404 IsCorrect = false;
405 break;
406 }
407 // Parse '('.
408 BalancedDelimiterTracker T(*this, tok::l_paren,
409 tok::annot_pragma_openmp_end);
410 IsCorrect =
411 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
412 IsCorrect;
413 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
414 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
417 // Parse expression.
418 VarDecl *OmpPrivParm =
420 getCurScope(), D);
421 // Check if initializer is omp_priv <init_expr> or something else.
422 if (Tok.is(tok::identifier) &&
423 Tok.getIdentifierInfo()->isStr("omp_priv")) {
424 ConsumeToken();
425 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
426 } else {
427 InitializerResult = Actions.ActOnFinishFullExpr(
429 /*DiscardedValue*/ false);
430 }
432 D, InitializerResult.get(), OmpPrivParm);
433 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
434 Tok.isNot(tok::annot_pragma_openmp_end)) {
435 TPA.Commit();
436 IsCorrect = false;
437 break;
438 }
439 IsCorrect =
440 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
441 }
442 }
443
444 ++I;
445 // Revert parsing if not the last type, otherwise accept it, we're done with
446 // parsing.
447 if (I != E)
448 TPA.Revert();
449 else
450 TPA.Commit();
451 }
453 getCurScope(), DRD, IsCorrect);
454}
455
456void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
457 // Parse declarator '=' initializer.
458 // If a '==' or '+=' is found, suggest a fixit to '='.
459 if (isTokenEqualOrEqualTypo()) {
460 ConsumeToken();
461
462 if (Tok.is(tok::code_completion)) {
463 cutOffParsing();
465 OmpPrivParm);
466 Actions.FinalizeDeclaration(OmpPrivParm);
467 return;
468 }
469
470 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
471 ExprResult Init = ParseInitializer();
472
473 if (Init.isInvalid()) {
474 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
475 Actions.ActOnInitializerError(OmpPrivParm);
476 } else {
477 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
478 /*DirectInit=*/false);
479 }
480 } else if (Tok.is(tok::l_paren)) {
481 // Parse C++ direct initializer: '(' expression-list ')'
482 BalancedDelimiterTracker T(*this, tok::l_paren);
483 T.consumeOpen();
484
485 ExprVector Exprs;
486
487 SourceLocation LParLoc = T.getOpenLocation();
488 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
489 QualType PreferredType =
491 OmpPrivParm->getType()->getCanonicalTypeInternal(),
492 OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
493 CalledSignatureHelp = true;
494 return PreferredType;
495 };
496 if (ParseExpressionList(Exprs, [&] {
497 PreferredType.enterFunctionArgument(Tok.getLocation(),
498 RunSignatureHelp);
499 })) {
500 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
501 RunSignatureHelp();
502 Actions.ActOnInitializerError(OmpPrivParm);
503 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
504 } else {
505 // Match the ')'.
506 SourceLocation RLoc = Tok.getLocation();
507 if (!T.consumeClose())
508 RLoc = T.getCloseLocation();
509
511 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
512 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
513 /*DirectInit=*/true);
514 }
515 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
516 // Parse C++0x braced-init-list.
517 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
518
519 ExprResult Init(ParseBraceInitializer());
520
521 if (Init.isInvalid()) {
522 Actions.ActOnInitializerError(OmpPrivParm);
523 } else {
524 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
525 /*DirectInit=*/true);
526 }
527 } else {
528 Actions.ActOnUninitializedDecl(OmpPrivParm);
529 }
530}
531
532/// Parses 'omp declare mapper' directive.
533///
534/// declare-mapper-directive:
535/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
536/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
537/// annot_pragma_openmp_end
538/// <mapper-identifier> and <var> are base language identifiers.
539///
541Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
542 bool IsCorrect = true;
543 // Parse '('
544 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
545 if (T.expectAndConsume(diag::err_expected_lparen_after,
546 getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
547 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
548 return DeclGroupPtrTy();
549 }
550
551 // Parse <mapper-identifier>
552 auto &DeclNames = Actions.getASTContext().DeclarationNames;
553 DeclarationName MapperId;
554 if (PP.LookAhead(0).is(tok::colon)) {
555 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
556 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
557 IsCorrect = false;
558 } else {
559 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
560 }
561 ConsumeToken();
562 // Consume ':'.
563 ExpectAndConsume(tok::colon);
564 } else {
565 // If no mapper identifier is provided, its name is "default" by default
566 MapperId =
567 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
568 }
569
570 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
571 return DeclGroupPtrTy();
572
573 // Parse <type> <var>
574 DeclarationName VName;
575 QualType MapperType;
577 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
578 if (ParsedType.isUsable())
579 MapperType = Actions.OpenMP().ActOnOpenMPDeclareMapperType(Range.getBegin(),
580 ParsedType);
581 if (MapperType.isNull())
582 IsCorrect = false;
583 if (!IsCorrect) {
584 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
585 return DeclGroupPtrTy();
586 }
587
588 // Consume ')'.
589 IsCorrect &= !T.consumeClose();
590 if (!IsCorrect) {
591 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
592 return DeclGroupPtrTy();
593 }
594
595 // Enter scope.
596 DeclarationNameInfo DirName;
598 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
600 ParseScope OMPDirectiveScope(this, ScopeFlags);
601 Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName,
602 getCurScope(), Loc);
603
604 // Add the mapper variable declaration.
605 ExprResult MapperVarRef =
607 getCurScope(), MapperType, Range.getBegin(), VName);
608
609 // Parse map clauses.
611 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
612 OpenMPClauseKind CKind = Tok.isAnnotation()
613 ? OMPC_unknown
614 : getOpenMPClauseKind(PP.getSpelling(Tok));
615 Actions.OpenMP().StartOpenMPClause(CKind);
616 OMPClause *Clause =
617 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
618 if (Clause)
619 Clauses.push_back(Clause);
620 else
621 IsCorrect = false;
622 // Skip ',' if any.
623 if (Tok.is(tok::comma))
624 ConsumeToken();
625 Actions.OpenMP().EndOpenMPClause();
626 }
627 if (Clauses.empty()) {
628 Diag(Tok, diag::err_omp_expected_clause)
629 << getOpenMPDirectiveName(OMPD_declare_mapper);
630 IsCorrect = false;
631 }
632
633 // Exit scope.
634 Actions.OpenMP().EndOpenMPDSABlock(nullptr);
635 OMPDirectiveScope.Exit();
637 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
638 Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
639 if (!IsCorrect)
640 return DeclGroupPtrTy();
641
642 return DG;
643}
644
645TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
646 DeclarationName &Name,
647 AccessSpecifier AS) {
648 // Parse the common declaration-specifiers piece.
649 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
650 DeclSpec DS(AttrFactory);
651 ParseSpecifierQualifierList(DS, AS, DSC);
652
653 // Parse the declarator.
655 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
656 ParseDeclarator(DeclaratorInfo);
657 Range = DeclaratorInfo.getSourceRange();
658 if (DeclaratorInfo.getIdentifier() == nullptr) {
659 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
660 return true;
661 }
662 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
663
665 DeclaratorInfo);
666}
667
668namespace {
669/// RAII that recreates function context for correct parsing of clauses of
670/// 'declare simd' construct.
671/// OpenMP, 2.8.2 declare simd Construct
672/// The expressions appearing in the clauses of this directive are evaluated in
673/// the scope of the arguments of the function declaration or definition.
674class FNContextRAII final {
675 Parser &P;
676 Sema::CXXThisScopeRAII *ThisScope;
678 bool HasFunScope = false;
679 FNContextRAII() = delete;
680 FNContextRAII(const FNContextRAII &) = delete;
681 FNContextRAII &operator=(const FNContextRAII &) = delete;
682
683public:
684 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {
685 Decl *D = *Ptr.get().begin();
686 NamedDecl *ND = dyn_cast<NamedDecl>(D);
687 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
688 Sema &Actions = P.getActions();
689
690 // Allow 'this' within late-parsed attributes.
691 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
692 ND && ND->isCXXInstanceMember());
693
694 // If the Decl is templatized, add template parameters to scope.
695 // FIXME: Track CurTemplateDepth?
696 P.ReenterTemplateScopes(Scopes, D);
697
698 // If the Decl is on a function, add function parameters to the scope.
700 HasFunScope = true;
701 Scopes.Enter(Scope::FnScope | Scope::DeclScope |
703 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
704 }
705 }
706 ~FNContextRAII() {
707 if (HasFunScope)
708 P.getActions().ActOnExitFunctionContext();
709 delete ThisScope;
710 }
711};
712} // namespace
713
714/// Parses clauses for 'declare simd' directive.
715/// clause:
716/// 'inbranch' | 'notinbranch'
717/// 'simdlen' '(' <expr> ')'
718/// { 'uniform' '(' <argument_list> ')' }
719/// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
720/// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
722 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
726 SourceRange BSRange;
727 const Token &Tok = P.getCurToken();
728 bool IsError = false;
729 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
730 if (Tok.isNot(tok::identifier))
731 break;
732 OMPDeclareSimdDeclAttr::BranchStateTy Out;
734 StringRef ClauseName = II->getName();
735 // Parse 'inranch|notinbranch' clauses.
736 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
737 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
738 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
739 << ClauseName
740 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
741 IsError = true;
742 }
743 BS = Out;
744 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
745 P.ConsumeToken();
746 } else if (ClauseName == "simdlen") {
747 if (SimdLen.isUsable()) {
748 P.Diag(Tok, diag::err_omp_more_one_clause)
749 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
750 IsError = true;
751 }
752 P.ConsumeToken();
753 SourceLocation RLoc;
754 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
755 if (SimdLen.isInvalid())
756 IsError = true;
757 } else {
758 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
759 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
760 CKind == OMPC_linear) {
762 SmallVectorImpl<Expr *> *Vars = &Uniforms;
763 if (CKind == OMPC_aligned) {
764 Vars = &Aligneds;
765 } else if (CKind == OMPC_linear) {
766 Data.ExtraModifier = OMPC_LINEAR_val;
767 Vars = &Linears;
768 }
769
770 P.ConsumeToken();
771 if (P.ParseOpenMPVarList(OMPD_declare_simd,
772 getOpenMPClauseKind(ClauseName), *Vars, Data))
773 IsError = true;
774 if (CKind == OMPC_aligned) {
775 Alignments.append(Aligneds.size() - Alignments.size(),
776 Data.DepModOrTailExpr);
777 } else if (CKind == OMPC_linear) {
778 assert(0 <= Data.ExtraModifier &&
779 Data.ExtraModifier <= OMPC_LINEAR_unknown &&
780 "Unexpected linear modifier.");
781 if (P.getActions().OpenMP().CheckOpenMPLinearModifier(
782 static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
783 Data.ExtraModifierLoc))
784 Data.ExtraModifier = OMPC_LINEAR_val;
785 LinModifiers.append(Linears.size() - LinModifiers.size(),
786 Data.ExtraModifier);
787 Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
788 }
789 } else
790 // TODO: add parsing of other clauses.
791 break;
792 }
793 // Skip ',' if any.
794 if (Tok.is(tok::comma))
795 P.ConsumeToken();
796 }
797 return IsError;
798}
799
800/// Parse clauses for '#pragma omp declare simd'.
802Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
804 PP.EnterToken(Tok, /*IsReinject*/ true);
805 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
806 /*IsReinject*/ true);
807 // Consume the previously pushed token.
808 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
809 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
810
811 FNContextRAII FnContext(*this, Ptr);
812 OMPDeclareSimdDeclAttr::BranchStateTy BS =
813 OMPDeclareSimdDeclAttr::BS_Undefined;
814 ExprResult Simdlen;
815 SmallVector<Expr *, 4> Uniforms;
816 SmallVector<Expr *, 4> Aligneds;
817 SmallVector<Expr *, 4> Alignments;
819 SmallVector<unsigned, 4> LinModifiers;
821 bool IsError =
822 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
823 Alignments, Linears, LinModifiers, Steps);
824 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
825 // Skip the last annot_pragma_openmp_end.
826 SourceLocation EndLoc = ConsumeAnnotationToken();
827 if (IsError)
828 return Ptr;
830 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
831 LinModifiers, Steps, SourceRange(Loc, EndLoc));
832}
833
834namespace {
835/// Constant used in the diagnostics to distinguish the levels in an OpenMP
836/// contexts: selector-set={selector(trait, ...), ...}, ....
837enum OMPContextLvl {
838 CONTEXT_SELECTOR_SET_LVL = 0,
839 CONTEXT_SELECTOR_LVL = 1,
840 CONTEXT_TRAIT_LVL = 2,
841};
842
843static StringRef stringLiteralParser(Parser &P) {
844 ExprResult Res = P.ParseStringLiteralExpression(true);
845 return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
846}
847
848static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
849 OMPContextLvl Lvl) {
850 if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {
852 StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
853 (void)P.ConsumeToken();
854 return Name;
855 }
856
857 if (tok::isStringLiteral(Tok.getKind()))
858 return stringLiteralParser(P);
859
860 P.Diag(Tok.getLocation(),
861 diag::warn_omp_declare_variant_string_literal_or_identifier)
862 << Lvl;
863 return "";
864}
865
866static bool checkForDuplicates(Parser &P, StringRef Name,
867 SourceLocation NameLoc,
868 llvm::StringMap<SourceLocation> &Seen,
869 OMPContextLvl Lvl) {
870 auto Res = Seen.try_emplace(Name, NameLoc);
871 if (Res.second)
872 return false;
873
874 // Each trait-set-selector-name, trait-selector-name and trait-name can
875 // only be specified once.
876 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
877 << Lvl << Name;
878 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
879 << Lvl << Name;
880 return true;
881}
882} // namespace
883
884void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
885 llvm::omp::TraitSet Set,
886 llvm::omp::TraitSelector Selector,
887 llvm::StringMap<SourceLocation> &Seen) {
888 TIProperty.Kind = TraitProperty::invalid;
889
890 SourceLocation NameLoc = Tok.getLocation();
891 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
892 if (Name.empty()) {
893 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
894 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
895 return;
896 }
897
898 TIProperty.RawString = Name;
899 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
900 if (TIProperty.Kind != TraitProperty::invalid) {
901 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
902 TIProperty.Kind = TraitProperty::invalid;
903 return;
904 }
905
906 // It follows diagnosis and helping notes.
907 // FIXME: We should move the diagnosis string generation into libFrontend.
908 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
909 << Name << getOpenMPContextTraitSelectorName(Selector)
910 << getOpenMPContextTraitSetName(Set);
911
912 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
913 if (SetForName != TraitSet::invalid) {
914 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
915 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
916 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
917 << Name << "<selector-name>"
918 << "(<property-name>)";
919 return;
920 }
921 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
922 if (SelectorForName != TraitSelector::invalid) {
923 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
924 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
925 bool AllowsTraitScore = false;
926 bool RequiresProperty = false;
927 isValidTraitSelectorForTraitSet(
928 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
929 AllowsTraitScore, RequiresProperty);
930 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
931 << getOpenMPContextTraitSetName(
932 getOpenMPContextTraitSetForSelector(SelectorForName))
933 << Name << (RequiresProperty ? "(<property-name>)" : "");
934 return;
935 }
936 for (const auto &PotentialSet :
937 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
938 TraitSet::device}) {
939 TraitProperty PropertyForName =
940 getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
941 if (PropertyForName == TraitProperty::invalid)
942 continue;
943 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
944 << getOpenMPContextTraitSetName(
945 getOpenMPContextTraitSetForProperty(PropertyForName))
946 << getOpenMPContextTraitSelectorName(
947 getOpenMPContextTraitSelectorForProperty(PropertyForName))
948 << ("(" + Name + ")").str();
949 return;
950 }
951 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
952 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
953}
954
956 OMPTraitProperty &TIProperty,
957 OMPTraitSelector &TISelector,
958 llvm::StringMap<SourceLocation> &Seen) {
959 assert(TISelector.Kind ==
960 llvm::omp::TraitSelector::implementation_extension &&
961 "Only for extension properties, e.g., "
962 "`implementation={extension(PROPERTY)}`");
963 if (TIProperty.Kind == TraitProperty::invalid)
964 return false;
965
966 if (TIProperty.Kind ==
967 TraitProperty::implementation_extension_disable_implicit_base)
968 return true;
969
970 if (TIProperty.Kind ==
971 TraitProperty::implementation_extension_allow_templates)
972 return true;
973
974 if (TIProperty.Kind ==
975 TraitProperty::implementation_extension_bind_to_declaration)
976 return true;
977
978 auto IsMatchExtension = [](OMPTraitProperty &TP) {
979 return (TP.Kind ==
980 llvm::omp::TraitProperty::implementation_extension_match_all ||
981 TP.Kind ==
982 llvm::omp::TraitProperty::implementation_extension_match_any ||
983 TP.Kind ==
984 llvm::omp::TraitProperty::implementation_extension_match_none);
985 };
986
987 if (IsMatchExtension(TIProperty)) {
988 for (OMPTraitProperty &SeenProp : TISelector.Properties)
989 if (IsMatchExtension(SeenProp)) {
990 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
991 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
992 SeenProp.Kind, SeenProp.RawString);
993 SourceLocation SeenLoc = Seen[SeenName];
994 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
995 << CONTEXT_TRAIT_LVL << SeenName;
996 return false;
997 }
998 return true;
999 }
1000
1001 llvm_unreachable("Unknown extension property!");
1002}
1003
1004void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
1005 llvm::omp::TraitSet Set,
1006 llvm::StringMap<SourceLocation> &Seen) {
1007 assert(TISelector.Kind != TraitSelector::user_condition &&
1008 "User conditions are special properties not handled here!");
1009
1010 SourceLocation PropertyLoc = Tok.getLocation();
1011 OMPTraitProperty TIProperty;
1012 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
1013
1014 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
1015 if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
1016 TISelector, Seen))
1017 TIProperty.Kind = TraitProperty::invalid;
1018
1019 // If we have an invalid property here we already issued a warning.
1020 if (TIProperty.Kind == TraitProperty::invalid) {
1021 if (PropertyLoc != Tok.getLocation())
1022 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1023 << CONTEXT_TRAIT_LVL;
1024 return;
1025 }
1026
1027 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
1028 TISelector.Kind, Set)) {
1029
1030 // If we make it here the property, selector, set, score, condition, ... are
1031 // all valid (or have been corrected). Thus we can record the property.
1032 TISelector.Properties.push_back(TIProperty);
1033 return;
1034 }
1035
1036 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
1037 << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1038 TIProperty.RawString)
1039 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1040 << getOpenMPContextTraitSetName(Set);
1041 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1042 << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1043 TIProperty.RawString)
1044 << getOpenMPContextTraitSelectorName(
1045 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
1046 << getOpenMPContextTraitSetName(
1047 getOpenMPContextTraitSetForProperty(TIProperty.Kind));
1048 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1049 << CONTEXT_TRAIT_LVL;
1050}
1051
1052void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
1053 llvm::omp::TraitSet Set,
1054 llvm::StringMap<SourceLocation> &Seen) {
1055 TISelector.Kind = TraitSelector::invalid;
1056
1057 SourceLocation NameLoc = Tok.getLocation();
1058 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
1059 if (Name.empty()) {
1060 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1061 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1062 return;
1063 }
1064
1065 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name);
1066 if (TISelector.Kind != TraitSelector::invalid) {
1067 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1068 TISelector.Kind = TraitSelector::invalid;
1069 return;
1070 }
1071
1072 // It follows diagnosis and helping notes.
1073 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1074 << Name << getOpenMPContextTraitSetName(Set);
1075
1076 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1077 if (SetForName != TraitSet::invalid) {
1078 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1079 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1080 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1081 << Name << "<selector-name>"
1082 << "<property-name>";
1083 return;
1084 }
1085 for (const auto &PotentialSet :
1086 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1087 TraitSet::device}) {
1088 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1089 PotentialSet, TraitSelector::invalid, Name);
1090 if (PropertyForName == TraitProperty::invalid)
1091 continue;
1092 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1093 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1094 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1095 << getOpenMPContextTraitSetName(
1096 getOpenMPContextTraitSetForProperty(PropertyForName))
1097 << getOpenMPContextTraitSelectorName(
1098 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1099 << ("(" + Name + ")").str();
1100 return;
1101 }
1102 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1103 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1104}
1105
1106/// Parse optional 'score' '(' <expr> ')' ':'.
1108 ExprResult ScoreExpr;
1109 llvm::SmallString<16> Buffer;
1110 StringRef SelectorName =
1111 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
1112 if (SelectorName != "score")
1113 return ScoreExpr;
1114 (void)P.ConsumeToken();
1115 SourceLocation RLoc;
1116 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
1117 // Parse ':'
1118 if (P.getCurToken().is(tok::colon))
1119 (void)P.ConsumeAnyToken();
1120 else
1121 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
1122 << "':'"
1123 << "score expression";
1124 return ScoreExpr;
1125}
1126
1127/// Parses an OpenMP context selector.
1128///
1129/// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')']
1130void Parser::parseOMPContextSelector(
1131 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
1132 llvm::StringMap<SourceLocation> &SeenSelectors) {
1133 unsigned short OuterPC = ParenCount;
1134
1135 // If anything went wrong we issue an error or warning and then skip the rest
1136 // of the selector. However, commas are ambiguous so we look for the nesting
1137 // of parentheses here as well.
1138 auto FinishSelector = [OuterPC, this]() -> void {
1139 bool Done = false;
1140 while (!Done) {
1141 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1142 tok::annot_pragma_openmp_end},
1144 ;
1145 if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
1146 (void)ConsumeParen();
1147 if (OuterPC <= ParenCount) {
1148 Done = true;
1149 break;
1150 }
1151 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
1152 Done = true;
1153 break;
1154 }
1155 (void)ConsumeAnyToken();
1156 }
1157 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1158 << CONTEXT_SELECTOR_LVL;
1159 };
1160
1161 SourceLocation SelectorLoc = Tok.getLocation();
1162 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
1163 if (TISelector.Kind == TraitSelector::invalid)
1164 return FinishSelector();
1165
1166 bool AllowsTraitScore = false;
1167 bool RequiresProperty = false;
1168 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
1169 RequiresProperty)) {
1170 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1171 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1172 << getOpenMPContextTraitSetName(Set);
1173 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1174 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1175 << getOpenMPContextTraitSetName(
1176 getOpenMPContextTraitSetForSelector(TISelector.Kind))
1177 << RequiresProperty;
1178 return FinishSelector();
1179 }
1180
1181 if (!RequiresProperty) {
1182 TISelector.Properties.push_back(
1183 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
1184 getOpenMPContextTraitSelectorName(TISelector.Kind)});
1185 return;
1186 }
1187
1188 if (!Tok.is(tok::l_paren)) {
1189 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1190 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1191 << getOpenMPContextTraitSetName(Set);
1192 return FinishSelector();
1193 }
1194
1195 if (TISelector.Kind == TraitSelector::user_condition) {
1196 SourceLocation RLoc;
1197 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
1198 if (!Condition.isUsable())
1199 return FinishSelector();
1200 TISelector.ScoreOrCondition = Condition.get();
1201 TISelector.Properties.push_back(
1202 {TraitProperty::user_condition_unknown, "<condition>"});
1203 return;
1204 }
1205
1206 BalancedDelimiterTracker BDT(*this, tok::l_paren,
1207 tok::annot_pragma_openmp_end);
1208 // Parse '('.
1209 (void)BDT.consumeOpen();
1210
1211 SourceLocation ScoreLoc = Tok.getLocation();
1212 ExprResult Score = parseContextScore(*this);
1213
1214 if (!AllowsTraitScore && !Score.isUnset()) {
1215 if (Score.isUsable()) {
1216 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1217 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1218 << getOpenMPContextTraitSetName(Set) << Score.get();
1219 } else {
1220 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1221 << getOpenMPContextTraitSelectorName(TISelector.Kind)
1222 << getOpenMPContextTraitSetName(Set) << "<invalid>";
1223 }
1224 Score = ExprResult();
1225 }
1226
1227 if (Score.isUsable())
1228 TISelector.ScoreOrCondition = Score.get();
1229
1230 llvm::StringMap<SourceLocation> SeenProperties;
1231 do {
1232 parseOMPContextProperty(TISelector, Set, SeenProperties);
1233 } while (TryConsumeToken(tok::comma));
1234
1235 // Parse ')'.
1236 BDT.consumeClose();
1237}
1238
1239void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
1240 llvm::StringMap<SourceLocation> &Seen) {
1241 TISet.Kind = TraitSet::invalid;
1242
1243 SourceLocation NameLoc = Tok.getLocation();
1244 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
1245 if (Name.empty()) {
1246 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1247 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1248 return;
1249 }
1250
1251 TISet.Kind = getOpenMPContextTraitSetKind(Name);
1252 if (TISet.Kind != TraitSet::invalid) {
1253 if (checkForDuplicates(*this, Name, NameLoc, Seen,
1254 CONTEXT_SELECTOR_SET_LVL))
1255 TISet.Kind = TraitSet::invalid;
1256 return;
1257 }
1258
1259 // It follows diagnosis and helping notes.
1260 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1261
1262 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
1263 if (SelectorForName != TraitSelector::invalid) {
1264 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1265 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1266 bool AllowsTraitScore = false;
1267 bool RequiresProperty = false;
1268 isValidTraitSelectorForTraitSet(
1269 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1270 AllowsTraitScore, RequiresProperty);
1271 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1272 << getOpenMPContextTraitSetName(
1273 getOpenMPContextTraitSetForSelector(SelectorForName))
1274 << Name << (RequiresProperty ? "(<property-name>)" : "");
1275 return;
1276 }
1277 for (const auto &PotentialSet :
1278 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1279 TraitSet::device}) {
1280 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1281 PotentialSet, TraitSelector::invalid, Name);
1282 if (PropertyForName == TraitProperty::invalid)
1283 continue;
1284 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1285 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1286 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1287 << getOpenMPContextTraitSetName(
1288 getOpenMPContextTraitSetForProperty(PropertyForName))
1289 << getOpenMPContextTraitSelectorName(
1290 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1291 << ("(" + Name + ")").str();
1292 return;
1293 }
1294 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1295 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1296}
1297
1298/// Parses an OpenMP context selector set.
1299///
1300/// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}'
1301void Parser::parseOMPContextSelectorSet(
1302 OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1303 auto OuterBC = BraceCount;
1304
1305 // If anything went wrong we issue an error or warning and then skip the rest
1306 // of the set. However, commas are ambiguous so we look for the nesting
1307 // of braces here as well.
1308 auto FinishSelectorSet = [this, OuterBC]() -> void {
1309 bool Done = false;
1310 while (!Done) {
1311 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1312 tok::annot_pragma_openmp_end},
1314 ;
1315 if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
1316 (void)ConsumeBrace();
1317 if (OuterBC <= BraceCount) {
1318 Done = true;
1319 break;
1320 }
1321 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
1322 Done = true;
1323 break;
1324 }
1325 (void)ConsumeAnyToken();
1326 }
1327 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1328 << CONTEXT_SELECTOR_SET_LVL;
1329 };
1330
1331 parseOMPTraitSetKind(TISet, SeenSets);
1332 if (TISet.Kind == TraitSet::invalid)
1333 return FinishSelectorSet();
1334
1335 // Parse '='.
1336 if (!TryConsumeToken(tok::equal))
1337 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1338 << "="
1339 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
1340 "\"")
1341 .str();
1342
1343 // Parse '{'.
1344 if (Tok.is(tok::l_brace)) {
1345 (void)ConsumeBrace();
1346 } else {
1347 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1348 << "{"
1349 << ("'=' that follows the context set name \"" +
1350 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1351 .str();
1352 }
1353
1354 llvm::StringMap<SourceLocation> SeenSelectors;
1355 do {
1356 OMPTraitSelector TISelector;
1357 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
1358 if (TISelector.Kind != TraitSelector::invalid &&
1359 !TISelector.Properties.empty())
1360 TISet.Selectors.push_back(TISelector);
1361 } while (TryConsumeToken(tok::comma));
1362
1363 // Parse '}'.
1364 if (Tok.is(tok::r_brace)) {
1365 (void)ConsumeBrace();
1366 } else {
1367 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1368 << "}"
1369 << ("context selectors for the context set \"" +
1370 getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1371 .str();
1372 }
1373}
1374
1375/// Parse OpenMP context selectors:
1376///
1377/// <trait-set-selector> [, <trait-set-selector>]*
1378bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
1379 llvm::StringMap<SourceLocation> SeenSets;
1380 do {
1381 OMPTraitSet TISet;
1382 parseOMPContextSelectorSet(TISet, SeenSets);
1383 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
1384 TI.Sets.push_back(TISet);
1385 } while (TryConsumeToken(tok::comma));
1386
1387 return false;
1388}
1389
1390/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
1391void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1392 CachedTokens &Toks,
1394 PP.EnterToken(Tok, /*IsReinject*/ true);
1395 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1396 /*IsReinject*/ true);
1397 // Consume the previously pushed token.
1398 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1399 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1400
1401 FNContextRAII FnContext(*this, Ptr);
1402 // Parse function declaration id.
1403 SourceLocation RLoc;
1404 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1405 // instead of MemberExprs.
1406 ExprResult AssociatedFunction;
1407 {
1408 // Do not mark function as is used to prevent its emission if this is the
1409 // only place where it is used.
1412 AssociatedFunction = ParseOpenMPParensExpr(
1413 getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1414 /*IsAddressOfOperand=*/true);
1415 }
1416 if (!AssociatedFunction.isUsable()) {
1417 if (!Tok.is(tok::annot_pragma_openmp_end))
1418 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1419 ;
1420 // Skip the last annot_pragma_openmp_end.
1421 (void)ConsumeAnnotationToken();
1422 return;
1423 }
1424
1425 OMPTraitInfo *ParentTI =
1426 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
1427 ASTContext &ASTCtx = Actions.getASTContext();
1428 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1429 SmallVector<Expr *, 6> AdjustNothing;
1430 SmallVector<Expr *, 6> AdjustNeedDevicePtr;
1432 SourceLocation AdjustArgsLoc, AppendArgsLoc;
1433
1434 // At least one clause is required.
1435 if (Tok.is(tok::annot_pragma_openmp_end)) {
1436 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1437 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1438 }
1439
1440 bool IsError = false;
1441 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1442 OpenMPClauseKind CKind = Tok.isAnnotation()
1443 ? OMPC_unknown
1444 : getOpenMPClauseKind(PP.getSpelling(Tok));
1445 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
1446 getLangOpts().OpenMP)) {
1447 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1448 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1449 IsError = true;
1450 }
1451 if (!IsError) {
1452 switch (CKind) {
1453 case OMPC_match:
1454 IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
1455 break;
1456 case OMPC_adjust_args: {
1457 AdjustArgsLoc = Tok.getLocation();
1458 ConsumeToken();
1461 IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
1462 Vars, Data);
1463 if (!IsError)
1464 llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
1465 ? AdjustNothing
1466 : AdjustNeedDevicePtr,
1467 Vars);
1468 break;
1469 }
1470 case OMPC_append_args:
1471 if (!AppendArgs.empty()) {
1472 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1473 << getOpenMPDirectiveName(OMPD_declare_variant)
1474 << getOpenMPClauseName(CKind) << 0;
1475 IsError = true;
1476 }
1477 if (!IsError) {
1478 AppendArgsLoc = Tok.getLocation();
1479 ConsumeToken();
1480 IsError = parseOpenMPAppendArgs(AppendArgs);
1481 }
1482 break;
1483 default:
1484 llvm_unreachable("Unexpected clause for declare variant.");
1485 }
1486 }
1487 if (IsError) {
1488 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1489 ;
1490 // Skip the last annot_pragma_openmp_end.
1491 (void)ConsumeAnnotationToken();
1492 return;
1493 }
1494 // Skip ',' if any.
1495 if (Tok.is(tok::comma))
1496 ConsumeToken();
1497 }
1498
1499 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1501 Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
1502 SourceRange(Loc, Tok.getLocation()));
1503
1504 if (DeclVarData && !TI.Sets.empty())
1506 DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
1507 AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
1508 SourceRange(Loc, Tok.getLocation()));
1509
1510 // Skip the last annot_pragma_openmp_end.
1511 (void)ConsumeAnnotationToken();
1512}
1513
1514bool Parser::parseOpenMPAppendArgs(
1515 SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
1516 bool HasError = false;
1517 // Parse '('.
1518 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1519 if (T.expectAndConsume(diag::err_expected_lparen_after,
1520 getOpenMPClauseName(OMPC_append_args).data()))
1521 return true;
1522
1523 // Parse the list of append-ops, each is;
1524 // interop(interop-type[,interop-type]...)
1525 while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
1526 ConsumeToken();
1527 BalancedDelimiterTracker IT(*this, tok::l_paren,
1528 tok::annot_pragma_openmp_end);
1529 if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
1530 return true;
1531
1532 OMPInteropInfo InteropInfo;
1533 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1534 HasError = true;
1535 else
1536 InteropInfos.push_back(InteropInfo);
1537
1538 IT.consumeClose();
1539 if (Tok.is(tok::comma))
1540 ConsumeToken();
1541 }
1542 if (!HasError && InteropInfos.empty()) {
1543 HasError = true;
1544 Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
1545 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1547 }
1548 HasError = T.consumeClose() || HasError;
1549 return HasError;
1550}
1551
1552bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1553 OMPTraitInfo &TI,
1554 OMPTraitInfo *ParentTI) {
1555 // Parse 'match'.
1556 OpenMPClauseKind CKind = Tok.isAnnotation()
1557 ? OMPC_unknown
1558 : getOpenMPClauseKind(PP.getSpelling(Tok));
1559 if (CKind != OMPC_match) {
1560 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1561 << (getLangOpts().OpenMP < 51 ? 0 : 1);
1562 return true;
1563 }
1564 (void)ConsumeToken();
1565 // Parse '('.
1566 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1567 if (T.expectAndConsume(diag::err_expected_lparen_after,
1568 getOpenMPClauseName(OMPC_match).data()))
1569 return true;
1570
1571 // Parse inner context selectors.
1572 parseOMPContextSelectors(Loc, TI);
1573
1574 // Parse ')'
1575 (void)T.consumeClose();
1576
1577 if (!ParentTI)
1578 return false;
1579
1580 // Merge the parent/outer trait info into the one we just parsed and diagnose
1581 // problems.
1582 // TODO: Keep some source location in the TI to provide better diagnostics.
1583 // TODO: Perform some kind of equivalence check on the condition and score
1584 // expressions.
1585 for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
1586 bool MergedSet = false;
1587 for (OMPTraitSet &Set : TI.Sets) {
1588 if (Set.Kind != ParentSet.Kind)
1589 continue;
1590 MergedSet = true;
1591 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
1592 bool MergedSelector = false;
1593 for (OMPTraitSelector &Selector : Set.Selectors) {
1594 if (Selector.Kind != ParentSelector.Kind)
1595 continue;
1596 MergedSelector = true;
1597 for (const OMPTraitProperty &ParentProperty :
1598 ParentSelector.Properties) {
1599 bool MergedProperty = false;
1600 for (OMPTraitProperty &Property : Selector.Properties) {
1601 // Ignore "equivalent" properties.
1602 if (Property.Kind != ParentProperty.Kind)
1603 continue;
1604
1605 // If the kind is the same but the raw string not, we don't want
1606 // to skip out on the property.
1607 MergedProperty |= Property.RawString == ParentProperty.RawString;
1608
1609 if (Property.RawString == ParentProperty.RawString &&
1610 Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
1611 continue;
1612
1613 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1614 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1615 } else if (Selector.ScoreOrCondition !=
1616 ParentSelector.ScoreOrCondition) {
1617 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1618 << getOpenMPContextTraitPropertyName(
1619 ParentProperty.Kind, ParentProperty.RawString)
1620 << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
1621 << getOpenMPContextTraitSetName(ParentSet.Kind);
1622 }
1623 }
1624 if (!MergedProperty)
1625 Selector.Properties.push_back(ParentProperty);
1626 }
1627 }
1628 if (!MergedSelector)
1629 Set.Selectors.push_back(ParentSelector);
1630 }
1631 }
1632 if (!MergedSet)
1633 TI.Sets.push_back(ParentSet);
1634 }
1635
1636 return false;
1637}
1638
1639/// <clause> [clause[ [,] clause] ... ]
1640///
1641/// clauses: for error directive
1642/// 'at' '(' compilation | execution ')'
1643/// 'severity' '(' fatal | warning ')'
1644/// 'message' '(' msg-string ')'
1645/// ....
1646void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
1649 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
1650 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1651 OpenMPClauseKind CKind = Tok.isAnnotation()
1652 ? OMPC_unknown
1653 : getOpenMPClauseKind(PP.getSpelling(Tok));
1654 Actions.OpenMP().StartOpenMPClause(CKind);
1655 OMPClause *Clause =
1656 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
1657 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1659 SeenClauses[unsigned(CKind)] = true;
1660 if (Clause != nullptr)
1661 Clauses.push_back(Clause);
1662 if (Tok.is(tok::annot_pragma_openmp_end)) {
1663 Actions.OpenMP().EndOpenMPClause();
1664 break;
1665 }
1666 // Skip ',' if any.
1667 if (Tok.is(tok::comma))
1668 ConsumeToken();
1669 Actions.OpenMP().EndOpenMPClause();
1670 }
1671}
1672
1673/// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
1674/// where
1675///
1676/// clause:
1677/// 'ext_IMPL_DEFINED'
1678/// 'absent' '(' directive-name [, directive-name]* ')'
1679/// 'contains' '(' directive-name [, directive-name]* ')'
1680/// 'holds' '(' scalar-expression ')'
1681/// 'no_openmp'
1682/// 'no_openmp_routines'
1683/// 'no_parallelism'
1684///
1685void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
1687 SmallVector<std::string, 4> Assumptions;
1688 bool SkippedClauses = false;
1689
1690 auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
1691 BalancedDelimiterTracker T(*this, tok::l_paren,
1692 tok::annot_pragma_openmp_end);
1693 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1694 return;
1695 T.skipToEnd();
1696 if (IssueNote && T.getCloseLocation().isValid())
1697 Diag(T.getCloseLocation(),
1698 diag::note_omp_assumption_clause_continue_here);
1699 };
1700
1701 /// Helper to determine which AssumptionClauseMapping (ACM) in the
1702 /// AssumptionClauseMappings table matches \p RawString. The return value is
1703 /// the index of the matching ACM into the table or -1 if there was no match.
1704 auto MatchACMClause = [&](StringRef RawString) {
1705 llvm::StringSwitch<int> SS(RawString);
1706 unsigned ACMIdx = 0;
1707 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1708 if (ACMI.StartsWith)
1709 SS.StartsWith(ACMI.Identifier, ACMIdx++);
1710 else
1711 SS.Case(ACMI.Identifier, ACMIdx++);
1712 }
1713 return SS.Default(-1);
1714 };
1715
1716 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1717 IdentifierInfo *II = nullptr;
1718 SourceLocation StartLoc = Tok.getLocation();
1719 int Idx = -1;
1720 if (Tok.isAnyIdentifier()) {
1721 II = Tok.getIdentifierInfo();
1722 Idx = MatchACMClause(II->getName());
1723 }
1725
1726 bool NextIsLPar = Tok.is(tok::l_paren);
1727 // Handle unknown clauses by skipping them.
1728 if (Idx == -1) {
1729 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1730 << llvm::omp::getOpenMPDirectiveName(DKind)
1731 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1732 if (NextIsLPar)
1733 SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
1734 SkippedClauses = true;
1735 continue;
1736 }
1737 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1738 if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1739 // TODO: We ignore absent, contains, and holds assumptions for now. We
1740 // also do not verify the content in the parenthesis at all.
1741 SkippedClauses = true;
1742 SkipBraces(II->getName(), /* IssueNote */ false);
1743 continue;
1744 }
1745
1746 if (NextIsLPar) {
1747 Diag(Tok.getLocation(),
1748 diag::warn_omp_unknown_assumption_clause_without_args)
1749 << II;
1750 SkipBraces(II->getName(), /* IssueNote */ true);
1751 }
1752
1753 assert(II && "Expected an identifier clause!");
1754 std::string Assumption = II->getName().str();
1755 if (ACMI.StartsWith)
1756 Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
1757 else
1758 Assumption = "omp_" + Assumption;
1759 Assumptions.push_back(Assumption);
1760 }
1761
1762 Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
1763 SkippedClauses);
1764}
1765
1766void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
1767 if (Actions.OpenMP().isInOpenMPAssumeScope())
1769 else
1770 Diag(Loc, diag::err_expected_begin_assumes);
1771}
1772
1773/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1774///
1775/// default-clause:
1776/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')
1777///
1778/// proc_bind-clause:
1779/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1780///
1781/// device_type-clause:
1782/// 'device_type' '(' 'host' | 'nohost' | 'any' )'
1783namespace {
1784struct SimpleClauseData {
1785 unsigned Type;
1787 SourceLocation LOpen;
1789 SourceLocation RLoc;
1790 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1792 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1793};
1794} // anonymous namespace
1795
1796static std::optional<SimpleClauseData>
1798 const Token &Tok = P.getCurToken();
1800 SourceLocation LOpen = P.ConsumeToken();
1801 // Parse '('.
1802 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1803 if (T.expectAndConsume(diag::err_expected_lparen_after,
1804 getOpenMPClauseName(Kind).data()))
1805 return std::nullopt;
1806
1808 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
1809 P.getLangOpts());
1811 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1812 Tok.isNot(tok::annot_pragma_openmp_end))
1813 P.ConsumeAnyToken();
1814
1815 // Parse ')'.
1816 SourceLocation RLoc = Tok.getLocation();
1817 if (!T.consumeClose())
1818 RLoc = T.getCloseLocation();
1819
1820 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1821}
1822
1823void Parser::ParseOMPDeclareTargetClauses(
1825 SourceLocation DeviceTypeLoc;
1826 bool RequiresToOrLinkOrIndirectClause = false;
1827 bool HasToOrLinkOrIndirectClause = false;
1828 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1829 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1830 bool HasIdentifier = Tok.is(tok::identifier);
1831 if (HasIdentifier) {
1832 // If we see any clause we need a to or link clause.
1833 RequiresToOrLinkOrIndirectClause = true;
1835 StringRef ClauseName = II->getName();
1836 bool IsDeviceTypeClause =
1837 getLangOpts().OpenMP >= 50 &&
1838 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1839
1840 bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
1841 getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1842 if (DTCI.Indirect && IsIndirectClause) {
1843 Diag(Tok, diag::err_omp_more_one_clause)
1844 << getOpenMPDirectiveName(OMPD_declare_target)
1845 << getOpenMPClauseName(OMPC_indirect) << 0;
1846 break;
1847 }
1848 bool IsToEnterOrLinkClause =
1849 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1850 assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
1851 "Cannot be both!");
1852
1853 // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1854 // `enter` clause.
1855 if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
1856 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1857 break;
1858 }
1859 if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
1860 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1861 break;
1862 }
1863
1864 if (!IsDeviceTypeClause && !IsIndirectClause &&
1865 DTCI.Kind == OMPD_begin_declare_target) {
1866 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1867 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
1868 break;
1869 }
1870 if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
1871 Diag(Tok, getLangOpts().OpenMP >= 52
1872 ? diag::err_omp_declare_target_unexpected_clause_52
1873 : diag::err_omp_declare_target_unexpected_clause)
1874 << ClauseName
1875 << (getLangOpts().OpenMP >= 51
1876 ? 4
1877 : getLangOpts().OpenMP >= 50 ? 2 : 1);
1878 break;
1879 }
1880
1881 if (IsToEnterOrLinkClause || IsIndirectClause)
1882 HasToOrLinkOrIndirectClause = true;
1883
1884 if (IsIndirectClause) {
1885 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
1886 break;
1887 continue;
1888 }
1889 // Parse 'device_type' clause and go to next clause if any.
1890 if (IsDeviceTypeClause) {
1891 std::optional<SimpleClauseData> DevTypeData =
1892 parseOpenMPSimpleClause(*this, OMPC_device_type);
1893 if (DevTypeData) {
1894 if (DeviceTypeLoc.isValid()) {
1895 // We already saw another device_type clause, diagnose it.
1896 Diag(DevTypeData->Loc,
1897 diag::warn_omp_more_one_device_type_clause);
1898 break;
1899 }
1900 switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
1901 case OMPC_DEVICE_TYPE_any:
1902 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1903 break;
1904 case OMPC_DEVICE_TYPE_host:
1905 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1906 break;
1907 case OMPC_DEVICE_TYPE_nohost:
1908 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1909 break;
1911 llvm_unreachable("Unexpected device_type");
1912 }
1913 DeviceTypeLoc = DevTypeData->Loc;
1914 }
1915 continue;
1916 }
1917 ConsumeToken();
1918 }
1919
1920 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1921 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1922 DeclarationNameInfo NameInfo) {
1924 getCurScope(), SS, NameInfo);
1925 if (!ND)
1926 return;
1928 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1929 if (!FirstMapping)
1930 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
1931 << NameInfo.getName();
1932 };
1933 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1934 /*AllowScopeSpecifier=*/true))
1935 break;
1936 }
1937
1938 if (Tok.is(tok::l_paren)) {
1939 Diag(Tok,
1940 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1941 break;
1942 }
1943 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
1944 Diag(Tok,
1945 getLangOpts().OpenMP >= 52
1946 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1947 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1948 break;
1949 }
1950
1951 // Consume optional ','.
1952 if (Tok.is(tok::comma))
1953 ConsumeToken();
1954 }
1955
1956 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1957 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1958
1959 // For declare target require at least 'to' or 'link' to be present.
1960 if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
1961 !HasToOrLinkOrIndirectClause)
1962 Diag(DTCI.Loc,
1963 getLangOpts().OpenMP >= 52
1964 ? diag::err_omp_declare_target_missing_enter_or_link_clause
1965 : diag::err_omp_declare_target_missing_to_or_link_clause)
1966 << (getLangOpts().OpenMP >= 51 ? 1 : 0);
1967
1968 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1969}
1970
1971void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1972 // The last seen token is annot_pragma_openmp_end - need to check for
1973 // extra tokens.
1974 if (Tok.is(tok::annot_pragma_openmp_end))
1975 return;
1976
1977 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1978 << getOpenMPDirectiveName(DKind);
1979 while (Tok.isNot(tok::annot_pragma_openmp_end))
1981}
1982
1983void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1984 OpenMPDirectiveKind ExpectedKind,
1985 OpenMPDirectiveKind FoundKind,
1986 SourceLocation BeginLoc,
1987 SourceLocation FoundLoc,
1988 bool SkipUntilOpenMPEnd) {
1989 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1990
1991 if (FoundKind == ExpectedKind) {
1993 skipUntilPragmaOpenMPEnd(ExpectedKind);
1994 return;
1995 }
1996
1997 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1998 << DiagSelection;
1999 Diag(BeginLoc, diag::note_matching)
2000 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
2001 if (SkipUntilOpenMPEnd)
2002 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
2003}
2004
2005void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
2006 OpenMPDirectiveKind EndDKind,
2007 SourceLocation DKLoc) {
2008 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
2009 Tok.getLocation(),
2010 /* SkipUntilOpenMPEnd */ false);
2011 // Skip the last annot_pragma_openmp_end.
2012 if (Tok.is(tok::annot_pragma_openmp_end))
2013 ConsumeAnnotationToken();
2014}
2015
2016/// Parsing of declarative OpenMP directives.
2017///
2018/// threadprivate-directive:
2019/// annot_pragma_openmp 'threadprivate' simple-variable-list
2020/// annot_pragma_openmp_end
2021///
2022/// allocate-directive:
2023/// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
2024/// annot_pragma_openmp_end
2025///
2026/// declare-reduction-directive:
2027/// annot_pragma_openmp 'declare' 'reduction' [...]
2028/// annot_pragma_openmp_end
2029///
2030/// declare-mapper-directive:
2031/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
2032/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
2033/// annot_pragma_openmp_end
2034///
2035/// declare-simd-directive:
2036/// annot_pragma_openmp 'declare simd' {<clause> [,]}
2037/// annot_pragma_openmp_end
2038/// <function declaration/definition>
2039///
2040/// requires directive:
2041/// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
2042/// annot_pragma_openmp_end
2043///
2044/// assumes directive:
2045/// annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ]
2046/// annot_pragma_openmp_end
2047/// or
2048/// annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ]
2049/// annot_pragma_openmp 'end assumes'
2050/// annot_pragma_openmp_end
2051///
2052Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
2053 AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
2054 DeclSpec::TST TagType, Decl *Tag) {
2055 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2056 "Not an OpenMP directive!");
2057 ParsingOpenMPDirectiveRAII DirScope(*this);
2058 ParenBraceBracketBalancer BalancerRAIIObj(*this);
2059
2061 OpenMPDirectiveKind DKind;
2062 if (Delayed) {
2063 TentativeParsingAction TPA(*this);
2064 Loc = ConsumeAnnotationToken();
2065 DKind = parseOpenMPDirectiveKind(*this);
2066 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
2067 // Need to delay parsing until completion of the parent class.
2068 TPA.Revert();
2069 CachedTokens Toks;
2070 unsigned Cnt = 1;
2071 Toks.push_back(Tok);
2072 while (Cnt && Tok.isNot(tok::eof)) {
2073 (void)ConsumeAnyToken();
2074 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
2075 ++Cnt;
2076 else if (Tok.is(tok::annot_pragma_openmp_end))
2077 --Cnt;
2078 Toks.push_back(Tok);
2079 }
2080 // Skip last annot_pragma_openmp_end.
2081 if (Cnt == 0)
2082 (void)ConsumeAnyToken();
2083 auto *LP = new LateParsedPragma(this, AS);
2084 LP->takeToks(Toks);
2085 getCurrentClass().LateParsedDeclarations.push_back(LP);
2086 return nullptr;
2087 }
2088 TPA.Commit();
2089 } else {
2090 Loc = ConsumeAnnotationToken();
2091 DKind = parseOpenMPDirectiveKind(*this);
2092 }
2093
2094 switch (DKind) {
2095 case OMPD_threadprivate: {
2096 ConsumeToken();
2097 DeclDirectiveListParserHelper Helper(this, DKind);
2098 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2099 /*AllowScopeSpecifier=*/true)) {
2100 skipUntilPragmaOpenMPEnd(DKind);
2101 // Skip the last annot_pragma_openmp_end.
2102 ConsumeAnnotationToken();
2104 Loc, Helper.getIdentifiers());
2105 }
2106 break;
2107 }
2108 case OMPD_allocate: {
2109 ConsumeToken();
2110 DeclDirectiveListParserHelper Helper(this, DKind);
2111 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2112 /*AllowScopeSpecifier=*/true)) {
2114 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2115 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
2116 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2117 OpenMPClauseKind CKind =
2118 Tok.isAnnotation() ? OMPC_unknown
2119 : getOpenMPClauseKind(PP.getSpelling(Tok));
2120 Actions.OpenMP().StartOpenMPClause(CKind);
2121 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2122 !SeenClauses[unsigned(CKind)]);
2123 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2125 SeenClauses[unsigned(CKind)] = true;
2126 if (Clause != nullptr)
2127 Clauses.push_back(Clause);
2128 if (Tok.is(tok::annot_pragma_openmp_end)) {
2129 Actions.OpenMP().EndOpenMPClause();
2130 break;
2131 }
2132 // Skip ',' if any.
2133 if (Tok.is(tok::comma))
2134 ConsumeToken();
2135 Actions.OpenMP().EndOpenMPClause();
2136 }
2137 skipUntilPragmaOpenMPEnd(DKind);
2138 }
2139 // Skip the last annot_pragma_openmp_end.
2140 ConsumeAnnotationToken();
2141 return Actions.OpenMP().ActOnOpenMPAllocateDirective(
2142 Loc, Helper.getIdentifiers(), Clauses);
2143 }
2144 break;
2145 }
2146 case OMPD_requires: {
2147 SourceLocation StartLoc = ConsumeToken();
2149 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2150 if (Tok.is(tok::annot_pragma_openmp_end)) {
2151 Diag(Tok, diag::err_omp_expected_clause)
2152 << getOpenMPDirectiveName(OMPD_requires);
2153 break;
2154 }
2155 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2156 OpenMPClauseKind CKind = Tok.isAnnotation()
2157 ? OMPC_unknown
2158 : getOpenMPClauseKind(PP.getSpelling(Tok));
2159 Actions.OpenMP().StartOpenMPClause(CKind);
2160 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
2161 !SeenClauses[unsigned(CKind)]);
2162 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2164 SeenClauses[unsigned(CKind)] = true;
2165 if (Clause != nullptr)
2166 Clauses.push_back(Clause);
2167 if (Tok.is(tok::annot_pragma_openmp_end)) {
2168 Actions.OpenMP().EndOpenMPClause();
2169 break;
2170 }
2171 // Skip ',' if any.
2172 if (Tok.is(tok::comma))
2173 ConsumeToken();
2174 Actions.OpenMP().EndOpenMPClause();
2175 }
2176 // Consume final annot_pragma_openmp_end
2177 if (Clauses.empty()) {
2178 Diag(Tok, diag::err_omp_expected_clause)
2179 << getOpenMPDirectiveName(OMPD_requires);
2180 ConsumeAnnotationToken();
2181 return nullptr;
2182 }
2183 ConsumeAnnotationToken();
2184 return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
2185 }
2186 case OMPD_error: {
2188 SourceLocation StartLoc = ConsumeToken();
2189 ParseOpenMPClauses(DKind, Clauses, StartLoc);
2190 Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
2192 /*InExContext = */ false);
2193 break;
2194 }
2195 case OMPD_assumes:
2196 case OMPD_begin_assumes:
2197 ParseOpenMPAssumesDirective(DKind, ConsumeToken());
2198 break;
2199 case OMPD_end_assumes:
2200 ParseOpenMPEndAssumesDirective(ConsumeToken());
2201 break;
2202 case OMPD_declare_reduction:
2203 ConsumeToken();
2204 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2205 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2206 // Skip the last annot_pragma_openmp_end.
2207 ConsumeAnnotationToken();
2208 return Res;
2209 }
2210 break;
2211 case OMPD_declare_mapper: {
2212 ConsumeToken();
2213 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2214 // Skip the last annot_pragma_openmp_end.
2215 ConsumeAnnotationToken();
2216 return Res;
2217 }
2218 break;
2219 }
2220 case OMPD_begin_declare_variant: {
2221 // The syntax is:
2222 // { #pragma omp begin declare variant clause }
2223 // <function-declaration-or-definition-sequence>
2224 // { #pragma omp end declare variant }
2225 //
2226 ConsumeToken();
2227 OMPTraitInfo *ParentTI =
2228 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
2229 ASTContext &ASTCtx = Actions.getASTContext();
2230 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
2231 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
2232 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
2233 ;
2234 // Skip the last annot_pragma_openmp_end.
2235 (void)ConsumeAnnotationToken();
2236 break;
2237 }
2238
2239 // Skip last tokens.
2240 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
2241
2242 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2243
2244 VariantMatchInfo VMI;
2245 TI.getAsVariantMatchInfo(ASTCtx, VMI);
2246
2247 std::function<void(StringRef)> DiagUnknownTrait =
2248 [this, Loc](StringRef ISATrait) {
2249 // TODO Track the selector locations in a way that is accessible here
2250 // to improve the diagnostic location.
2251 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2252 };
2253 TargetOMPContext OMPCtx(
2254 ASTCtx, std::move(DiagUnknownTrait),
2255 /* CurrentFunctionDecl */ nullptr,
2256 /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>());
2257
2258 if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
2260 break;
2261 }
2262
2263 // Elide all the code till the matching end declare variant was found.
2264 unsigned Nesting = 1;
2265 SourceLocation DKLoc;
2266 OpenMPDirectiveKind DK = OMPD_unknown;
2267 do {
2268 DKLoc = Tok.getLocation();
2269 DK = parseOpenMPDirectiveKind(*this);
2270 if (DK == OMPD_end_declare_variant)
2271 --Nesting;
2272 else if (DK == OMPD_begin_declare_variant)
2273 ++Nesting;
2274 if (!Nesting || isEofOrEom())
2275 break;
2277 } while (true);
2278
2279 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
2280 DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
2281 if (isEofOrEom())
2282 return nullptr;
2283 break;
2284 }
2285 case OMPD_end_declare_variant: {
2286 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2288 else
2289 Diag(Loc, diag::err_expected_begin_declare_variant);
2290 ConsumeToken();
2291 break;
2292 }
2293 case OMPD_declare_variant:
2294 case OMPD_declare_simd: {
2295 // The syntax is:
2296 // { #pragma omp declare {simd|variant} }
2297 // <function-declaration-or-definition>
2298 //
2299 CachedTokens Toks;
2300 Toks.push_back(Tok);
2301 ConsumeToken();
2302 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2303 Toks.push_back(Tok);
2305 }
2306 Toks.push_back(Tok);
2308
2309 DeclGroupPtrTy Ptr;
2310 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2311 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2312 TagType, Tag);
2313 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
2314 // Here we expect to see some function declaration.
2315 if (AS == AS_none) {
2317 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2318 MaybeParseCXX11Attributes(Attrs);
2319 ParsingDeclSpec PDS(*this);
2320 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2321 } else {
2322 Ptr =
2323 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
2324 }
2325 }
2326 if (!Ptr) {
2327 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2328 << (DKind == OMPD_declare_simd ? 0 : 1);
2329 return DeclGroupPtrTy();
2330 }
2331 if (DKind == OMPD_declare_simd)
2332 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2333 assert(DKind == OMPD_declare_variant &&
2334 "Expected declare variant directive only");
2335 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2336 return Ptr;
2337 }
2338 case OMPD_begin_declare_target:
2339 case OMPD_declare_target: {
2341 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2342 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2343 if (HasClauses)
2344 ParseOMPDeclareTargetClauses(DTCI);
2345 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2346 !HasClauses ||
2347 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2348
2349 // Skip the last annot_pragma_openmp_end.
2351
2352 if (HasImplicitMappings) {
2354 return nullptr;
2355 }
2356
2359 for (auto &It : DTCI.ExplicitlyMapped)
2360 Decls.push_back(It.first);
2361 return Actions.BuildDeclaratorGroup(Decls);
2362 }
2363 case OMPD_end_declare_target: {
2364 if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
2365 Diag(Tok, diag::err_omp_unexpected_directive)
2366 << 1 << getOpenMPDirectiveName(DKind);
2367 break;
2368 }
2371 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2372 return nullptr;
2373 }
2374 case OMPD_assume: {
2375 Diag(Tok, diag::err_omp_unexpected_directive)
2376 << 1 << getOpenMPDirectiveName(DKind);
2377 break;
2378 }
2379 case OMPD_unknown:
2380 Diag(Tok, diag::err_omp_unknown_directive);
2381 break;
2382 default:
2383 switch (getDirectiveCategory(DKind)) {
2384 case Category::Executable:
2385 case Category::Meta:
2386 case Category::Subsidiary:
2387 case Category::Utility:
2388 Diag(Tok, diag::err_omp_unexpected_directive)
2389 << 1 << getOpenMPDirectiveName(DKind);
2390 break;
2391 case Category::Declarative:
2392 case Category::Informational:
2393 break;
2394 }
2395 }
2396 while (Tok.isNot(tok::annot_pragma_openmp_end))
2399 return nullptr;
2400}
2401
2402StmtResult Parser::ParseOpenMPExecutableDirective(
2403 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2404 bool ReadDirectiveWithinMetadirective) {
2405 assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2406
2407 bool HasAssociatedStatement = true;
2408 Association Assoc = getDirectiveAssociation(DKind);
2409
2410 // OMPD_ordered has None as association, but it comes in two variants,
2411 // the second of which is associated with a block.
2412 // OMPD_scan and OMPD_section are both "separating", but section is treated
2413 // as if it was associated with a statement, while scan is not.
2414 if (DKind != OMPD_ordered && DKind != OMPD_section &&
2415 (Assoc == Association::None || Assoc == Association::Separating)) {
2416 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2417 ParsedStmtContext()) {
2418 Diag(Tok, diag::err_omp_immediate_directive)
2419 << getOpenMPDirectiveName(DKind) << 0;
2420 if (DKind == OMPD_error) {
2421 SkipUntil(tok::annot_pragma_openmp_end);
2422 return StmtError();
2423 }
2424 }
2425 HasAssociatedStatement = false;
2426 }
2427
2428 SourceLocation EndLoc;
2430 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2431 DeclarationNameInfo DirName;
2432 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2433 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2435
2436 // Special processing for flush and depobj clauses.
2437 Token ImplicitTok;
2438 bool ImplicitClauseAllowed = false;
2439 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2440 ImplicitTok = Tok;
2441 ImplicitClauseAllowed = true;
2442 }
2443 ConsumeToken();
2444 // Parse directive name of the 'critical' directive if any.
2445 if (DKind == OMPD_critical) {
2446 BalancedDelimiterTracker T(*this, tok::l_paren,
2447 tok::annot_pragma_openmp_end);
2448 if (!T.consumeOpen()) {
2449 if (Tok.isAnyIdentifier()) {
2450 DirName =
2453 } else {
2454 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2455 }
2456 T.consumeClose();
2457 }
2458 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2459 CancelRegion = parseOpenMPDirectiveKind(*this);
2460 if (Tok.isNot(tok::annot_pragma_openmp_end))
2461 ConsumeToken();
2462 }
2463
2464 if (isOpenMPLoopDirective(DKind))
2465 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2466 if (isOpenMPSimdDirective(DKind))
2467 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2468 ParseScope OMPDirectiveScope(this, ScopeFlags);
2469 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2470 Loc);
2471
2472 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2473 // If we are parsing for a directive within a metadirective, the directive
2474 // ends with a ')'.
2475 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2476 while (Tok.isNot(tok::annot_pragma_openmp_end))
2478 break;
2479 }
2480 bool HasImplicitClause = false;
2481 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2482 HasImplicitClause = true;
2483 // Push copy of the current token back to stream to properly parse
2484 // pseudo-clause OMPFlushClause or OMPDepobjClause.
2485 PP.EnterToken(Tok, /*IsReinject*/ true);
2486 PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2488 }
2489 OpenMPClauseKind CKind = Tok.isAnnotation()
2490 ? OMPC_unknown
2491 : getOpenMPClauseKind(PP.getSpelling(Tok));
2492 if (HasImplicitClause) {
2493 assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2494 if (DKind == OMPD_flush) {
2495 CKind = OMPC_flush;
2496 } else {
2497 assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2498 CKind = OMPC_depobj;
2499 }
2500 }
2501 // No more implicit clauses allowed.
2502 ImplicitClauseAllowed = false;
2503 Actions.OpenMP().StartOpenMPClause(CKind);
2504 HasImplicitClause = false;
2505 OMPClause *Clause =
2506 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2507 SeenClauses[unsigned(CKind)] = true;
2508 if (Clause)
2509 Clauses.push_back(Clause);
2510
2511 // Skip ',' if any.
2512 if (Tok.is(tok::comma))
2513 ConsumeToken();
2514 Actions.OpenMP().EndOpenMPClause();
2515 }
2516 // End location of the directive.
2517 EndLoc = Tok.getLocation();
2518 // Consume final annot_pragma_openmp_end.
2519 ConsumeAnnotationToken();
2520
2521 if (DKind == OMPD_ordered) {
2522 // If the depend or doacross clause is specified, the ordered construct
2523 // is a stand-alone directive.
2524 for (auto CK : {OMPC_depend, OMPC_doacross}) {
2525 if (SeenClauses[unsigned(CK)]) {
2526 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2527 ParsedStmtContext()) {
2528 Diag(Loc, diag::err_omp_immediate_directive)
2529 << getOpenMPDirectiveName(DKind) << 1 << getOpenMPClauseName(CK);
2530 }
2531 HasAssociatedStatement = false;
2532 }
2533 }
2534 }
2535
2536 if (DKind == OMPD_tile && !SeenClauses[unsigned(OMPC_sizes)]) {
2537 Diag(Loc, diag::err_omp_required_clause)
2538 << getOpenMPDirectiveName(OMPD_tile) << "sizes";
2539 }
2540
2541 StmtResult AssociatedStmt;
2542 if (HasAssociatedStatement) {
2543 // The body is a block scope like in Lambdas and Blocks.
2544 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2545 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2546 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2547 // should have at least one compound statement scope within it.
2548 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2549 {
2551 AssociatedStmt = ParseStatement();
2552
2553 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2554 getLangOpts().OpenMPIRBuilder)
2555 AssociatedStmt =
2556 Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
2557 }
2558 AssociatedStmt =
2559 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2560 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2561 DKind == OMPD_target_exit_data) {
2562 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2563 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2564 Actions.ActOnCompoundStmt(Loc, Loc, {},
2565 /*isStmtExpr=*/false));
2566 AssociatedStmt =
2567 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2568 }
2569
2571 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2572
2573 // Exit scope.
2574 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2575 OMPDirectiveScope.Exit();
2576
2577 return Directive;
2578}
2579
2580StmtResult Parser::ParseOpenMPInformationalDirective(
2581 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2582 bool ReadDirectiveWithinMetadirective) {
2583 assert(isOpenMPInformationalDirective(DKind) &&
2584 "Unexpected directive category");
2585
2586 bool HasAssociatedStatement = true;
2587
2589 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2590 DeclarationNameInfo DirName;
2591 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2593 ParseScope OMPDirectiveScope(this, ScopeFlags);
2594
2595 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2596 Loc);
2597
2598 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2599 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2600 while (Tok.isNot(tok::annot_pragma_openmp_end))
2602 break;
2603 }
2604
2605 OpenMPClauseKind CKind = Tok.isAnnotation()
2606 ? OMPC_unknown
2607 : getOpenMPClauseKind(PP.getSpelling(Tok));
2608 Actions.OpenMP().StartOpenMPClause(CKind);
2609 OMPClause *Clause =
2610 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2611 SeenClauses[unsigned(CKind)] = true;
2612 if (Clause)
2613 Clauses.push_back(Clause);
2614
2615 if (Tok.is(tok::comma))
2616 ConsumeToken();
2617 Actions.OpenMP().EndOpenMPClause();
2618 }
2619
2620 SourceLocation EndLoc = Tok.getLocation();
2621 ConsumeAnnotationToken();
2622
2623 StmtResult AssociatedStmt;
2624 if (HasAssociatedStatement) {
2625 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2626 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2627 {
2629 AssociatedStmt = ParseStatement();
2630 }
2631 AssociatedStmt =
2632 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2633 }
2634
2636 DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2637
2638 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2639 OMPDirectiveScope.Exit();
2640
2641 return Directive;
2642}
2643
2644/// Parsing of declarative or executable OpenMP directives.
2645///
2646/// threadprivate-directive:
2647/// annot_pragma_openmp 'threadprivate' simple-variable-list
2648/// annot_pragma_openmp_end
2649///
2650/// allocate-directive:
2651/// annot_pragma_openmp 'allocate' simple-variable-list
2652/// annot_pragma_openmp_end
2653///
2654/// declare-reduction-directive:
2655/// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
2656/// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
2657/// ('omp_priv' '=' <expression>|<function_call>) ')']
2658/// annot_pragma_openmp_end
2659///
2660/// declare-mapper-directive:
2661/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
2662/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
2663/// annot_pragma_openmp_end
2664///
2665/// executable-directive:
2666/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
2667/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
2668/// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
2669/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error'
2670/// | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
2671/// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
2672/// 'master taskloop' | 'master taskloop simd' | 'parallel master
2673/// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
2674/// enter data' | 'target exit data' | 'target parallel' | 'target
2675/// parallel for' | 'target update' | 'distribute parallel for' |
2676/// 'distribute paralle for simd' | 'distribute simd' | 'target parallel
2677/// for simd' | 'target simd' | 'teams distribute' | 'teams distribute
2678/// simd' | 'teams distribute parallel for simd' | 'teams distribute
2679/// parallel for' | 'target teams' | 'target teams distribute' | 'target
2680/// teams distribute parallel for' | 'target teams distribute parallel
2681/// for simd' | 'target teams distribute simd' | 'masked' |
2682/// 'parallel masked' {clause} annot_pragma_openmp_end
2683///
2684StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2685 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2686 if (!ReadDirectiveWithinMetadirective)
2687 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2688 "Not an OpenMP directive!");
2689 ParsingOpenMPDirectiveRAII DirScope(*this);
2690 ParenBraceBracketBalancer BalancerRAIIObj(*this);
2691 SourceLocation Loc = ReadDirectiveWithinMetadirective
2692 ? Tok.getLocation()
2693 : ConsumeAnnotationToken();
2695 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2696 Diag(Tok, diag::err_omp_unknown_directive);
2697 return StmtError();
2698 }
2699
2701
2702 bool IsExecutable = [&]() {
2703 if (DKind == OMPD_error) // OMPD_error is handled as executable
2704 return true;
2705 auto Res = getDirectiveCategory(DKind);
2706 return Res == Category::Executable || Res == Category::Subsidiary;
2707 }();
2708
2709 if (IsExecutable) {
2710 Directive = ParseOpenMPExecutableDirective(
2711 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2712 assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2713 return Directive;
2714 }
2715
2716 switch (DKind) {
2717 case OMPD_nothing:
2718 ConsumeToken();
2719 // If we are parsing the directive within a metadirective, the directive
2720 // ends with a ')'.
2721 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
2722 while (Tok.isNot(tok::annot_pragma_openmp_end))
2724 else
2725 skipUntilPragmaOpenMPEnd(DKind);
2726 if (Tok.is(tok::annot_pragma_openmp_end))
2727 ConsumeAnnotationToken();
2728 // return an empty statement
2729 return StmtEmpty();
2730 case OMPD_metadirective: {
2731 ConsumeToken();
2733
2734 // First iteration of parsing all clauses of metadirective.
2735 // This iteration only parses and collects all context selector ignoring the
2736 // associated directives.
2737 TentativeParsingAction TPA(*this);
2738 ASTContext &ASTContext = Actions.getASTContext();
2739
2740 BalancedDelimiterTracker T(*this, tok::l_paren,
2741 tok::annot_pragma_openmp_end);
2742 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2743 OpenMPClauseKind CKind = Tok.isAnnotation()
2744 ? OMPC_unknown
2745 : getOpenMPClauseKind(PP.getSpelling(Tok));
2747
2748 // Parse '('.
2749 if (T.expectAndConsume(diag::err_expected_lparen_after,
2750 getOpenMPClauseName(CKind).data()))
2751 return Directive;
2752
2754 if (CKind == OMPC_when) {
2755 // parse and get OMPTraitInfo to pass to the When clause
2756 parseOMPContextSelectors(Loc, TI);
2757 if (TI.Sets.size() == 0) {
2758 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
2759 TPA.Commit();
2760 return Directive;
2761 }
2762
2763 // Parse ':'
2764 if (Tok.is(tok::colon))
2766 else {
2767 Diag(Tok, diag::err_omp_expected_colon) << "when clause";
2768 TPA.Commit();
2769 return Directive;
2770 }
2771 }
2772 // Skip Directive for now. We will parse directive in the second iteration
2773 int paren = 0;
2774 while (Tok.isNot(tok::r_paren) || paren != 0) {
2775 if (Tok.is(tok::l_paren))
2776 paren++;
2777 if (Tok.is(tok::r_paren))
2778 paren--;
2779 if (Tok.is(tok::annot_pragma_openmp_end)) {
2780 Diag(Tok, diag::err_omp_expected_punc)
2781 << getOpenMPClauseName(CKind) << 0;
2782 TPA.Commit();
2783 return Directive;
2784 }
2786 }
2787 // Parse ')'
2788 if (Tok.is(tok::r_paren))
2789 T.consumeClose();
2790
2791 VariantMatchInfo VMI;
2793
2794 VMIs.push_back(VMI);
2795 }
2796
2797 TPA.Revert();
2798 // End of the first iteration. Parser is reset to the start of metadirective
2799
2800 std::function<void(StringRef)> DiagUnknownTrait =
2801 [this, Loc](StringRef ISATrait) {
2802 // TODO Track the selector locations in a way that is accessible here
2803 // to improve the diagnostic location.
2804 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2805 };
2806 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2807 /* CurrentFunctionDecl */ nullptr,
2809
2810 // A single match is returned for OpenMP 5.0
2811 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2812
2813 int Idx = 0;
2814 // In OpenMP 5.0 metadirective is either replaced by another directive or
2815 // ignored.
2816 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2817 // found by getBestWhenMatchForContext.
2818 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2819 // OpenMP 5.0 implementation - Skip to the best index found.
2820 if (Idx++ != BestIdx) {
2821 ConsumeToken(); // Consume clause name
2822 T.consumeOpen(); // Consume '('
2823 int paren = 0;
2824 // Skip everything inside the clause
2825 while (Tok.isNot(tok::r_paren) || paren != 0) {
2826 if (Tok.is(tok::l_paren))
2827 paren++;
2828 if (Tok.is(tok::r_paren))
2829 paren--;
2831 }
2832 // Parse ')'
2833 if (Tok.is(tok::r_paren))
2834 T.consumeClose();
2835 continue;
2836 }
2837
2838 OpenMPClauseKind CKind = Tok.isAnnotation()
2839 ? OMPC_unknown
2840 : getOpenMPClauseKind(PP.getSpelling(Tok));
2842
2843 // Parse '('.
2844 T.consumeOpen();
2845
2846 // Skip ContextSelectors for when clause
2847 if (CKind == OMPC_when) {
2849 // parse and skip the ContextSelectors
2850 parseOMPContextSelectors(Loc, TI);
2851
2852 // Parse ':'
2854 }
2855
2856 // If no directive is passed, skip in OpenMP 5.0.
2857 // TODO: Generate nothing directive from OpenMP 5.1.
2858 if (Tok.is(tok::r_paren)) {
2859 SkipUntil(tok::annot_pragma_openmp_end);
2860 break;
2861 }
2862
2863 // Parse Directive
2864 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2865 StmtCtx,
2866 /*ReadDirectiveWithinMetadirective=*/true);
2867 break;
2868 }
2869 break;
2870 }
2871 case OMPD_threadprivate: {
2872 // FIXME: Should this be permitted in C++?
2873 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2874 ParsedStmtContext()) {
2875 Diag(Tok, diag::err_omp_immediate_directive)
2876 << getOpenMPDirectiveName(DKind) << 0;
2877 }
2878 ConsumeToken();
2879 DeclDirectiveListParserHelper Helper(this, DKind);
2880 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2881 /*AllowScopeSpecifier=*/false)) {
2882 skipUntilPragmaOpenMPEnd(DKind);
2884 Loc, Helper.getIdentifiers());
2885 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2886 }
2887 SkipUntil(tok::annot_pragma_openmp_end);
2888 break;
2889 }
2890 case OMPD_allocate: {
2891 // FIXME: Should this be permitted in C++?
2892 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2893 ParsedStmtContext()) {
2894 Diag(Tok, diag::err_omp_immediate_directive)
2895 << getOpenMPDirectiveName(DKind) << 0;
2896 }
2897 ConsumeToken();
2898 DeclDirectiveListParserHelper Helper(this, DKind);
2899 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2900 /*AllowScopeSpecifier=*/false)) {
2902 if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2903 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2904 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2905 OpenMPClauseKind CKind =
2906 Tok.isAnnotation() ? OMPC_unknown
2907 : getOpenMPClauseKind(PP.getSpelling(Tok));
2908 Actions.OpenMP().StartOpenMPClause(CKind);
2909 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2910 !SeenClauses[unsigned(CKind)]);
2911 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2913 SeenClauses[unsigned(CKind)] = true;
2914 if (Clause != nullptr)
2915 Clauses.push_back(Clause);
2916 if (Tok.is(tok::annot_pragma_openmp_end)) {
2917 Actions.OpenMP().EndOpenMPClause();
2918 break;
2919 }
2920 // Skip ',' if any.
2921 if (Tok.is(tok::comma))
2922 ConsumeToken();
2923 Actions.OpenMP().EndOpenMPClause();
2924 }
2925 skipUntilPragmaOpenMPEnd(DKind);
2926 }
2928 Loc, Helper.getIdentifiers(), Clauses);
2929 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2930 }
2931 SkipUntil(tok::annot_pragma_openmp_end);
2932 break;
2933 }
2934 case OMPD_declare_reduction:
2935 ConsumeToken();
2936 if (DeclGroupPtrTy Res =
2937 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2938 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2940 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2941 } else {
2942 SkipUntil(tok::annot_pragma_openmp_end);
2943 }
2944 break;
2945 case OMPD_declare_mapper: {
2946 ConsumeToken();
2947 if (DeclGroupPtrTy Res =
2948 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2949 // Skip the last annot_pragma_openmp_end.
2950 ConsumeAnnotationToken();
2951 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2952 } else {
2953 SkipUntil(tok::annot_pragma_openmp_end);
2954 }
2955 break;
2956 }
2957 case OMPD_declare_target: {
2959 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2960 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2961 if (HasClauses)
2962 ParseOMPDeclareTargetClauses(DTCI);
2963 bool HasImplicitMappings =
2964 !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2965
2966 if (HasImplicitMappings) {
2967 Diag(Tok, diag::err_omp_unexpected_directive)
2968 << 1 << getOpenMPDirectiveName(DKind);
2969 SkipUntil(tok::annot_pragma_openmp_end);
2970 break;
2971 }
2972
2973 // Skip the last annot_pragma_openmp_end.
2975
2977 break;
2978 }
2979 case OMPD_declare_simd:
2980 case OMPD_begin_declare_target:
2981 case OMPD_end_declare_target:
2982 case OMPD_requires:
2983 case OMPD_begin_declare_variant:
2984 case OMPD_end_declare_variant:
2985 case OMPD_declare_variant:
2986 Diag(Tok, diag::err_omp_unexpected_directive)
2987 << 1 << getOpenMPDirectiveName(DKind);
2988 SkipUntil(tok::annot_pragma_openmp_end);
2989 break;
2990 case OMPD_assume: {
2991 ConsumeToken();
2992 Directive = ParseOpenMPInformationalDirective(
2993 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2994 assert(!Directive.isUnset() &&
2995 "Informational directive remains unprocessed");
2996 return Directive;
2997 }
2998 case OMPD_unknown:
2999 default:
3000 Diag(Tok, diag::err_omp_unknown_directive);
3001 SkipUntil(tok::annot_pragma_openmp_end);
3002 break;
3003 }
3004 return Directive;
3005}
3006
3007// Parses simple list:
3008// simple-variable-list:
3009// '(' id-expression {, id-expression} ')'
3010//
3011bool Parser::ParseOpenMPSimpleVarList(
3013 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
3014 &Callback,
3015 bool AllowScopeSpecifier) {
3016 // Parse '('.
3017 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3018 if (T.expectAndConsume(diag::err_expected_lparen_after,
3019 getOpenMPDirectiveName(Kind).data()))
3020 return true;
3021 bool IsCorrect = true;
3022 bool NoIdentIsFound = true;
3023
3024 // Read tokens while ')' or annot_pragma_openmp_end is not found.
3025 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
3026 CXXScopeSpec SS;
3027 UnqualifiedId Name;
3028 // Read var name.
3029 Token PrevTok = Tok;
3030 NoIdentIsFound = false;
3031
3032 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
3033 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
3034 /*ObjectHasErrors=*/false, false)) {
3035 IsCorrect = false;
3036 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3038 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
3039 /*ObjectHadErrors=*/false, false, false,
3040 false, false, nullptr, Name)) {
3041 IsCorrect = false;
3042 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3044 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
3045 Tok.isNot(tok::annot_pragma_openmp_end)) {
3046 IsCorrect = false;
3047 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3049 Diag(PrevTok.getLocation(), diag::err_expected)
3050 << tok::identifier
3051 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
3052 } else {
3053 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
3054 }
3055 // Consume ','.
3056 if (Tok.is(tok::comma)) {
3057 ConsumeToken();
3058 }
3059 }
3060
3061 if (NoIdentIsFound) {
3062 Diag(Tok, diag::err_expected) << tok::identifier;
3063 IsCorrect = false;
3064 }
3065
3066 // Parse ')'.
3067 IsCorrect = !T.consumeClose() && IsCorrect;
3068
3069 return !IsCorrect;
3070}
3071
3072OMPClause *Parser::ParseOpenMPSizesClause() {
3073 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3074 SmallVector<Expr *, 4> ValExprs;
3075 if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
3076 ValExprs))
3077 return nullptr;
3078
3079 return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
3080 OpenLoc, CloseLoc);
3081}
3082
3083OMPClause *Parser::ParseOpenMPPermutationClause() {
3084 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3085 SmallVector<Expr *> ArgExprs;
3086 if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,
3087 CloseLoc, ArgExprs,
3088 /*ReqIntConst=*/true))
3089 return nullptr;
3090
3091 return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,
3092 OpenLoc, CloseLoc);
3093}
3094
3095OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
3098
3099 // Parse '('.
3100 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3101 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
3102 return nullptr;
3104 do {
3105 CXXScopeSpec SS;
3106 Token Replacement;
3107 ExprResult Allocator =
3108 getLangOpts().CPlusPlus
3109 ? ParseCXXIdExpression()
3110 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
3111 Replacement);
3112 if (Allocator.isInvalid()) {
3113 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3115 break;
3116 }
3117 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3118 D.Allocator = Allocator.get();
3119 if (Tok.is(tok::l_paren)) {
3120 BalancedDelimiterTracker T(*this, tok::l_paren,
3121 tok::annot_pragma_openmp_end);
3122 T.consumeOpen();
3123 ExprResult AllocatorTraits =
3124 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3125 T.consumeClose();
3126 if (AllocatorTraits.isInvalid()) {
3127 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3129 break;
3130 }
3131 D.AllocatorTraits = AllocatorTraits.get();
3132 D.LParenLoc = T.getOpenLocation();
3133 D.RParenLoc = T.getCloseLocation();
3134 }
3135 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3136 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
3137 // Parse ','
3138 if (Tok.is(tok::comma))
3140 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
3141 T.consumeClose();
3142 return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3143 Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
3144}
3145
3146/// Parsing of OpenMP clauses.
3147///
3148/// clause:
3149/// if-clause | final-clause | num_threads-clause | safelen-clause |
3150/// default-clause | private-clause | firstprivate-clause | shared-clause
3151/// | linear-clause | aligned-clause | collapse-clause | bind-clause |
3152/// lastprivate-clause | reduction-clause | proc_bind-clause |
3153/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
3154/// mergeable-clause | flush-clause | read-clause | write-clause |
3155/// update-clause | capture-clause | seq_cst-clause | device-clause |
3156/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
3157/// thread_limit-clause | priority-clause | grainsize-clause |
3158/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
3159/// from-clause | is_device_ptr-clause | task_reduction-clause |
3160/// in_reduction-clause | allocator-clause | allocate-clause |
3161/// acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
3162/// depobj-clause | destroy-clause | detach-clause | inclusive-clause |
3163/// exclusive-clause | uses_allocators-clause | use_device_addr-clause |
3164/// has_device_addr
3165///
3166OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
3167 OpenMPClauseKind CKind, bool FirstClause) {
3168 OMPClauseKind = CKind;
3169 OMPClause *Clause = nullptr;
3170 bool ErrorFound = false;
3171 bool WrongDirective = false;
3172 // Check if clause is allowed for the given directive.
3173 if (CKind != OMPC_unknown &&
3174 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
3175 Diag(Tok, diag::err_omp_unexpected_clause)
3176 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3177 ErrorFound = true;
3178 WrongDirective = true;
3179 }
3180
3181 switch (CKind) {
3182 case OMPC_final:
3183 case OMPC_num_threads:
3184 case OMPC_safelen:
3185 case OMPC_simdlen:
3186 case OMPC_collapse:
3187 case OMPC_ordered:
3188 case OMPC_priority:
3189 case OMPC_grainsize:
3190 case OMPC_num_tasks:
3191 case OMPC_hint:
3192 case OMPC_allocator:
3193 case OMPC_depobj:
3194 case OMPC_detach:
3195 case OMPC_novariants:
3196 case OMPC_nocontext:
3197 case OMPC_filter:
3198 case OMPC_partial:
3199 case OMPC_align:
3200 case OMPC_message:
3201 case OMPC_ompx_dyn_cgroup_mem:
3202 // OpenMP [2.5, Restrictions]
3203 // At most one num_threads clause can appear on the directive.
3204 // OpenMP [2.8.1, simd construct, Restrictions]
3205 // Only one safelen clause can appear on a simd directive.
3206 // Only one simdlen clause can appear on a simd directive.
3207 // Only one collapse clause can appear on a simd directive.
3208 // OpenMP [2.11.1, task Construct, Restrictions]
3209 // At most one if clause can appear on the directive.
3210 // At most one final clause can appear on the directive.
3211 // OpenMP [teams Construct, Restrictions]
3212 // At most one num_teams clause can appear on the directive.
3213 // At most one thread_limit clause can appear on the directive.
3214 // OpenMP [2.9.1, task Construct, Restrictions]
3215 // At most one priority clause can appear on the directive.
3216 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3217 // At most one grainsize clause can appear on the directive.
3218 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3219 // At most one num_tasks clause can appear on the directive.
3220 // OpenMP [2.11.3, allocate Directive, Restrictions]
3221 // At most one allocator clause can appear on the directive.
3222 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3223 // At most one detach clause can appear on the directive.
3224 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3225 // At most one novariants clause can appear on a dispatch directive.
3226 // At most one nocontext clause can appear on a dispatch directive.
3227 // OpenMP [5.1, error directive, Restrictions]
3228 // At most one message clause can appear on the directive
3229 if (!FirstClause) {
3230 Diag(Tok, diag::err_omp_more_one_clause)
3231 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3232 ErrorFound = true;
3233 }
3234
3235 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3236 PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
3237 Clause = ParseOpenMPClause(CKind, WrongDirective);
3238 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
3239 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3240 else
3241 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3242 break;
3243 case OMPC_fail:
3244 case OMPC_default:
3245 case OMPC_proc_bind:
3246 case OMPC_atomic_default_mem_order:
3247 case OMPC_at:
3248 case OMPC_severity:
3249 case OMPC_bind:
3250 // OpenMP [2.14.3.1, Restrictions]
3251 // Only a single default clause may be specified on a parallel, task or
3252 // teams directive.
3253 // OpenMP [2.5, parallel Construct, Restrictions]
3254 // At most one proc_bind clause can appear on the directive.
3255 // OpenMP [5.0, Requires directive, Restrictions]
3256 // At most one atomic_default_mem_order clause can appear
3257 // on the directive
3258 // OpenMP [5.1, error directive, Restrictions]
3259 // At most one at clause can appear on the directive
3260 // At most one severity clause can appear on the directive
3261 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3262 // At most one bind clause can appear on a loop directive.
3263 if (!FirstClause) {
3264 Diag(Tok, diag::err_omp_more_one_clause)
3265 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3266 ErrorFound = true;
3267 }
3268
3269 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3270 break;
3271 case OMPC_device:
3272 case OMPC_schedule:
3273 case OMPC_dist_schedule:
3274 case OMPC_defaultmap:
3275 case OMPC_order:
3276 // OpenMP [2.7.1, Restrictions, p. 3]
3277 // Only one schedule clause can appear on a loop directive.
3278 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3279 // At most one defaultmap clause can appear on the directive.
3280 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3281 // At most one device clause can appear on the directive.
3282 // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3283 // At most one order clause may appear on a construct.
3284 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3285 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3286 Diag(Tok, diag::err_omp_more_one_clause)
3287 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3288 ErrorFound = true;
3289 }
3290 [[fallthrough]];
3291 case OMPC_if:
3292 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3293 break;
3294 case OMPC_holds:
3295 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3296 break;
3297 case OMPC_nowait:
3298 case OMPC_untied:
3299 case OMPC_mergeable:
3300 case OMPC_read:
3301 case OMPC_write:
3302 case OMPC_capture:
3303 case OMPC_compare:
3304 case OMPC_seq_cst:
3305 case OMPC_acq_rel:
3306 case OMPC_acquire:
3307 case OMPC_release:
3308 case OMPC_relaxed:
3309 case OMPC_weak:
3310 case OMPC_threads:
3311 case OMPC_simd:
3312 case OMPC_nogroup:
3313 case OMPC_unified_address:
3314 case OMPC_unified_shared_memory:
3315 case OMPC_reverse_offload:
3316 case OMPC_dynamic_allocators:
3317 case OMPC_full:
3318 // OpenMP [2.7.1, Restrictions, p. 9]
3319 // Only one ordered clause can appear on a loop directive.
3320 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3321 // Only one nowait clause can appear on a for directive.
3322 // OpenMP [5.0, Requires directive, Restrictions]
3323 // Each of the requires clauses can appear at most once on the directive.
3324 if (!FirstClause) {
3325 Diag(Tok, diag::err_omp_more_one_clause)
3326 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3327 ErrorFound = true;
3328 }
3329
3330 Clause = ParseOpenMPClause(CKind, WrongDirective);
3331 break;
3332 case OMPC_update:
3333 if (!FirstClause) {
3334 Diag(Tok, diag::err_omp_more_one_clause)
3335 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3336 ErrorFound = true;
3337 }
3338
3339 Clause = (DKind == OMPD_depobj)
3340 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
3341 : ParseOpenMPClause(CKind, WrongDirective);
3342 break;
3343 case OMPC_num_teams:
3344 case OMPC_thread_limit:
3345 if (!FirstClause) {
3346 Diag(Tok, diag::err_omp_more_one_clause)
3347 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3348 ErrorFound = true;
3349 }
3350 [[fallthrough]];
3351 case OMPC_private:
3352 case OMPC_firstprivate:
3353 case OMPC_lastprivate:
3354 case OMPC_shared:
3355 case OMPC_reduction:
3356 case OMPC_task_reduction:
3357 case OMPC_in_reduction:
3358 case OMPC_linear:
3359 case OMPC_aligned:
3360 case OMPC_copyin:
3361 case OMPC_copyprivate:
3362 case OMPC_flush:
3363 case OMPC_depend:
3364 case OMPC_map:
3365 case OMPC_to:
3366 case OMPC_from:
3367 case OMPC_use_device_ptr:
3368 case OMPC_use_device_addr:
3369 case OMPC_is_device_ptr:
3370 case OMPC_has_device_addr:
3371 case OMPC_allocate:
3372 case OMPC_nontemporal:
3373 case OMPC_inclusive:
3374 case OMPC_exclusive:
3375 case OMPC_affinity:
3376 case OMPC_doacross:
3377 case OMPC_enter:
3378 if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
3379 CKind == OMPC_depend)
3380 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3381 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3382 break;
3383 case OMPC_sizes:
3384 if (!FirstClause) {
3385 Diag(Tok, diag::err_omp_more_one_clause)
3386 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3387 ErrorFound = true;
3388 }
3389
3390 Clause = ParseOpenMPSizesClause();
3391 break;
3392 case OMPC_permutation:
3393 if (!FirstClause) {
3394 Diag(Tok, diag::err_omp_more_one_clause)
3395 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3396 ErrorFound = true;
3397 }
3398 Clause = ParseOpenMPPermutationClause();
3399 break;
3400 case OMPC_uses_allocators:
3401 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3402 break;
3403 case OMPC_destroy:
3404 if (DKind != OMPD_interop) {
3405 if (!FirstClause) {
3406 Diag(Tok, diag::err_omp_more_one_clause)
3407 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3408 ErrorFound = true;
3409 }
3410 Clause = ParseOpenMPClause(CKind, WrongDirective);
3411 break;
3412 }
3413 [[fallthrough]];
3414 case OMPC_init:
3415 case OMPC_use:
3416 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3417 break;
3418 case OMPC_device_type:
3419 case OMPC_unknown:
3420 skipUntilPragmaOpenMPEnd(DKind);
3421 break;
3422 case OMPC_threadprivate:
3423 case OMPC_uniform:
3424 case OMPC_match:
3425 if (!WrongDirective)
3426 Diag(Tok, diag::err_omp_unexpected_clause)
3427 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3428 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
3429 break;
3430 case OMPC_absent:
3431 case OMPC_contains: {
3433 SourceLocation LLoc = Tok.getLocation();
3434 SourceLocation RLoc;
3436 BalancedDelimiterTracker T(*this, tok::l_paren);
3437 T.consumeOpen();
3438 do {
3439 OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
3440 if (DK == OMPD_unknown) {
3441 skipUntilPragmaOpenMPEnd(OMPD_assume);
3442 Diag(Tok, diag::err_omp_unexpected_clause)
3443 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3444 break;
3445 }
3447 DKVec.push_back(DK);
3448 ConsumeToken();
3449 } else {
3450 Diag(Tok, diag::err_omp_unexpected_clause)
3451 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3452 }
3453 } while (TryConsumeToken(tok::comma));
3454 RLoc = Tok.getLocation();
3455 T.consumeClose();
3456 Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
3457 CKind, DKVec, Loc, LLoc, RLoc);
3458 break;
3459 }
3460 case OMPC_no_openmp:
3461 case OMPC_no_openmp_routines:
3462 case OMPC_no_parallelism: {
3463 if (!FirstClause) {
3464 Diag(Tok, diag::err_omp_more_one_clause)
3465 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3466 ErrorFound = true;
3467 }
3469 Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
3470 CKind, Loc, Tok.getLocation());
3471 break;
3472 }
3473 case OMPC_ompx_attribute:
3474 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3475 break;
3476 case OMPC_ompx_bare:
3477 if (DKind == llvm::omp::Directive::OMPD_target) {
3478 // Flang splits the combined directives which requires OMPD_target to be
3479 // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
3480 // to explicitly check whether this clause is applied to an `omp target`
3481 // without `teams` and emit an error.
3482 Diag(Tok, diag::err_omp_unexpected_clause)
3483 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3484 ErrorFound = true;
3485 WrongDirective = true;
3486 }
3487 if (WrongDirective)
3488 Diag(Tok, diag::note_ompx_bare_clause)
3489 << getOpenMPClauseName(CKind) << "target teams";
3490 if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3491 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3492 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3493 ErrorFound = true;
3494 }
3495 Clause = ParseOpenMPClause(CKind, WrongDirective);
3496 break;
3497 default:
3498 break;
3499 }
3500 return ErrorFound ? nullptr : Clause;
3501}
3502
3503/// Parses simple expression in parens for single-expression clauses of OpenMP
3504/// constructs.
3505/// \param RLoc Returned location of right paren.
3507 SourceLocation &RLoc,
3508 bool IsAddressOfOperand) {
3509 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3510 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3511 return ExprError();
3512
3513 SourceLocation ELoc = Tok.getLocation();
3514 ExprResult LHS(
3515 ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast));
3516 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3517 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3518
3519 // Parse ')'.
3520 RLoc = Tok.getLocation();
3521 if (!T.consumeClose())
3522 RLoc = T.getCloseLocation();
3523
3524 return Val;
3525}
3526
3527/// Parsing of OpenMP clauses with single expressions like 'final',
3528/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
3529/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
3530/// 'detach'.
3531///
3532/// final-clause:
3533/// 'final' '(' expression ')'
3534///
3535/// num_threads-clause:
3536/// 'num_threads' '(' expression ')'
3537///
3538/// safelen-clause:
3539/// 'safelen' '(' expression ')'
3540///
3541/// simdlen-clause:
3542/// 'simdlen' '(' expression ')'
3543///
3544/// collapse-clause:
3545/// 'collapse' '(' expression ')'
3546///
3547/// priority-clause:
3548/// 'priority' '(' expression ')'
3549///
3550/// grainsize-clause:
3551/// 'grainsize' '(' expression ')'
3552///
3553/// num_tasks-clause:
3554/// 'num_tasks' '(' expression ')'
3555///
3556/// hint-clause:
3557/// 'hint' '(' expression ')'
3558///
3559/// allocator-clause:
3560/// 'allocator' '(' expression ')'
3561///
3562/// detach-clause:
3563/// 'detach' '(' event-handler-expression ')'
3564///
3565/// align-clause
3566/// 'align' '(' positive-integer-constant ')'
3567///
3568/// holds-clause
3569/// 'holds' '(' expression ')'
3570///
3571OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3572 bool ParseOnly) {
3574 SourceLocation LLoc = Tok.getLocation();
3575 SourceLocation RLoc;
3576
3577 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
3578
3579 if (Val.isInvalid())
3580 return nullptr;
3581
3582 if (ParseOnly)
3583 return nullptr;
3584 return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3585 LLoc, RLoc);
3586}
3587
3588/// Parse indirect clause for '#pragma omp declare target' directive.
3589/// 'indirect' '[' '(' invoked-by-fptr ')' ']'
3590/// where invoked-by-fptr is a constant boolean expression that evaluates to
3591/// true or false at compile time.
3592bool Parser::ParseOpenMPIndirectClause(
3593 SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3595 SourceLocation RLoc;
3596
3597 if (Tok.isNot(tok::l_paren)) {
3598 if (ParseOnly)
3599 return false;
3600 DTCI.Indirect = nullptr;
3601 return true;
3602 }
3603
3604 ExprResult Val =
3605 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3606 if (Val.isInvalid())
3607 return false;
3608
3609 if (ParseOnly)
3610 return false;
3611
3612 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3613 !Val.get()->isInstantiationDependent() &&
3615 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3616 if (Ret.isInvalid())
3617 return false;
3618 llvm::APSInt Result;
3621 if (Ret.isInvalid())
3622 return false;
3623 DTCI.Indirect = Val.get();
3624 return true;
3625 }
3626 return false;
3627}
3628
3629/// Parses a comma-separated list of interop-types and a prefer_type list.
3630///
3631bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3632 OpenMPClauseKind Kind) {
3633 const Token &Tok = getCurToken();
3634 bool HasError = false;
3635 bool IsTarget = false;
3636 bool IsTargetSync = false;
3637
3638 while (Tok.is(tok::identifier)) {
3639 // Currently prefer_type is only allowed with 'init' and it must be first.
3640 bool PreferTypeAllowed = Kind == OMPC_init &&
3641 InteropInfo.PreferTypes.empty() && !IsTarget &&
3642 !IsTargetSync;
3643 if (Tok.getIdentifierInfo()->isStr("target")) {
3644 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3645 // Each interop-type may be specified on an action-clause at most
3646 // once.
3647 if (IsTarget)
3648 Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3649 IsTarget = true;
3650 ConsumeToken();
3651 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3652 if (IsTargetSync)
3653 Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3654 IsTargetSync = true;
3655 ConsumeToken();
3656 } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3657 PreferTypeAllowed) {
3658 ConsumeToken();
3659 BalancedDelimiterTracker PT(*this, tok::l_paren,
3660 tok::annot_pragma_openmp_end);
3661 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3662 HasError = true;
3663
3664 while (Tok.isNot(tok::r_paren)) {
3666 ExprResult LHS = ParseCastExpression(AnyCastExpr);
3667 ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
3668 ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3669 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3670 /*DiscardedValue=*/false);
3671 if (PTExpr.isUsable()) {
3672 InteropInfo.PreferTypes.push_back(PTExpr.get());
3673 } else {
3674 HasError = true;
3675 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3677 }
3678
3679 if (Tok.is(tok::comma))
3680 ConsumeToken();
3681 }
3682 PT.consumeClose();
3683 } else {
3684 HasError = true;
3685 Diag(Tok, diag::err_omp_expected_interop_type);
3686 ConsumeToken();
3687 }
3688 if (!Tok.is(tok::comma))
3689 break;
3690 ConsumeToken();
3691 }
3692
3693 if (!HasError && !IsTarget && !IsTargetSync) {
3694 Diag(Tok, diag::err_omp_expected_interop_type);
3695 HasError = true;
3696 }
3697
3698 if (Kind == OMPC_init) {
3699 if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
3700 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3701 if (Tok.is(tok::colon))
3702 ConsumeToken();
3703 }
3704
3705 // As of OpenMP 5.1,there are two interop-types, "target" and
3706 // "targetsync". Either or both are allowed for a single interop.
3707 InteropInfo.IsTarget = IsTarget;
3708 InteropInfo.IsTargetSync = IsTargetSync;
3709
3710 return HasError;
3711}
3712
3713/// Parsing of OpenMP clauses that use an interop-var.
3714///
3715/// init-clause:
3716/// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
3717///
3718/// destroy-clause:
3719/// destroy(interop-var)
3720///
3721/// use-clause:
3722/// use(interop-var)
3723///
3724/// interop-modifier:
3725/// prefer_type(preference-list)
3726///
3727/// preference-list:
3728/// foreign-runtime-id [, foreign-runtime-id]...
3729///
3730/// foreign-runtime-id:
3731/// <string-literal> | <constant-integral-expression>
3732///
3733/// interop-type:
3734/// target | targetsync
3735///
3736OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3737 bool ParseOnly) {
3739 // Parse '('.
3740 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3741 if (T.expectAndConsume(diag::err_expected_lparen_after,
3742 getOpenMPClauseName(Kind).data()))
3743 return nullptr;
3744
3745 bool InteropError = false;
3746 OMPInteropInfo InteropInfo;
3747 if (Kind == OMPC_init)
3748 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3749
3750 // Parse the variable.
3751 SourceLocation VarLoc = Tok.getLocation();
3752 ExprResult InteropVarExpr =
3754 if (!InteropVarExpr.isUsable()) {
3755 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3757 }
3758
3759 // Parse ')'.
3760 SourceLocation RLoc = Tok.getLocation();
3761 if (!T.consumeClose())
3762 RLoc = T.getCloseLocation();
3763
3764 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3765 return nullptr;
3766
3767 if (Kind == OMPC_init)
3768 return Actions.OpenMP().ActOnOpenMPInitClause(
3769 InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
3770 RLoc);
3771 if (Kind == OMPC_use)
3772 return Actions.OpenMP().ActOnOpenMPUseClause(
3773 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3774
3775 if (Kind == OMPC_destroy)
3776 return Actions.OpenMP().ActOnOpenMPDestroyClause(
3777 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3778
3779 llvm_unreachable("Unexpected interop variable clause.");
3780}
3781
3782OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
3784 // Parse '('.
3785 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3786 if (T.expectAndConsume(diag::err_expected_lparen_after,
3787 getOpenMPClauseName(OMPC_ompx_attribute).data()))
3788 return nullptr;
3789
3790 ParsedAttributes ParsedAttrs(AttrFactory);
3791 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
3792
3793 // Parse ')'.
3794 if (T.consumeClose())
3795 return nullptr;
3796
3797 if (ParseOnly)
3798 return nullptr;
3799
3800 SmallVector<Attr *> Attrs;
3801 for (const ParsedAttr &PA : ParsedAttrs) {
3802 switch (PA.getKind()) {
3803 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
3804 if (!PA.checkExactlyNumArgs(Actions, 2))
3805 continue;
3806 if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
3807 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
3808 Attrs.push_back(A);
3809 continue;
3810 case ParsedAttr::AT_AMDGPUWavesPerEU:
3811 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3812 !PA.checkAtMostNumArgs(Actions, 2))
3813 continue;
3814 if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
3815 PA, PA.getArgAsExpr(0),
3816 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
3817 Attrs.push_back(A);
3818 continue;
3819 case ParsedAttr::AT_CUDALaunchBounds:
3820 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3821 !PA.checkAtMostNumArgs(Actions, 2))
3822 continue;
3823 if (auto *A = Actions.CreateLaunchBoundsAttr(
3824 PA, PA.getArgAsExpr(0),
3825 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
3826 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
3827 Attrs.push_back(A);
3828 continue;
3829 default:
3830 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3831 continue;
3832 };
3833 }
3834
3835 return Actions.OpenMP().ActOnOpenMPXAttributeClause(
3836 Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
3837}
3838
3839/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
3840///
3841/// default-clause:
3842/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')'
3843///
3844/// proc_bind-clause:
3845/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')'
3846///
3847/// bind-clause:
3848/// 'bind' '(' 'teams' | 'parallel' | 'thread' ')'
3849///
3850/// update-clause:
3851/// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' |
3852/// 'inoutset' ')'
3853///
3854OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
3855 bool ParseOnly) {
3856 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
3857 if (!Val || ParseOnly)
3858 return nullptr;
3859 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3860 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
3861 static_cast<DefaultKind>(Val->Type) ==
3862 OMP_DEFAULT_firstprivate)) {
3863 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3864 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
3865 OMP_DEFAULT_private
3866 ? OMPC_private
3867 : OMPC_firstprivate)
3868 << getOpenMPClauseName(OMPC_default) << "5.1";
3869 return nullptr;
3870 }
3871 return Actions.OpenMP().ActOnOpenMPSimpleClause(
3872 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
3873}
3874
3875/// Parsing of OpenMP clauses like 'ordered'.
3876///
3877/// ordered-clause:
3878/// 'ordered'
3879///
3880/// nowait-clause:
3881/// 'nowait'
3882///
3883/// untied-clause:
3884/// 'untied'
3885///
3886/// mergeable-clause:
3887/// 'mergeable'
3888///
3889/// read-clause:
3890/// 'read'
3891///
3892/// threads-clause:
3893/// 'threads'
3894///
3895/// simd-clause:
3896/// 'simd'
3897///
3898/// nogroup-clause:
3899/// 'nogroup'
3900///
3901OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
3904
3905 if (ParseOnly)
3906 return nullptr;
3907 return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
3908}
3909
3910/// Parsing of OpenMP clauses with single expressions and some additional
3911/// argument like 'schedule' or 'dist_schedule'.
3912///
3913/// schedule-clause:
3914/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
3915/// ')'
3916///
3917/// if-clause:
3918/// 'if' '(' [ directive-name-modifier ':' ] expression ')'
3919///
3920/// defaultmap:
3921/// 'defaultmap' '(' modifier [ ':' kind ] ')'
3922///
3923/// device-clause:
3924/// 'device' '(' [ device-modifier ':' ] expression ')'
3925///
3926OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
3927 OpenMPClauseKind Kind,
3928 bool ParseOnly) {
3930 SourceLocation DelimLoc;
3931 // Parse '('.
3932 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3933 if (T.expectAndConsume(diag::err_expected_lparen_after,
3934 getOpenMPClauseName(Kind).data()))
3935 return nullptr;
3936
3937 ExprResult Val;
3940 if (Kind == OMPC_schedule) {
3941 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3942 Arg.resize(NumberOfElements);
3943 KLoc.resize(NumberOfElements);
3944 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
3945 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
3946 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
3947 unsigned KindModifier = getOpenMPSimpleClauseType(
3948 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3949 if (KindModifier > OMPC_SCHEDULE_unknown) {
3950 // Parse 'modifier'
3951 Arg[Modifier1] = KindModifier;
3952 KLoc[Modifier1] = Tok.getLocation();
3953 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3954 Tok.isNot(tok::annot_pragma_openmp_end))
3956 if (Tok.is(tok::comma)) {
3957 // Parse ',' 'modifier'
3959 KindModifier = getOpenMPSimpleClauseType(
3960 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3961 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
3962 ? KindModifier
3964 KLoc[Modifier2] = Tok.getLocation();
3965 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3966 Tok.isNot(tok::annot_pragma_openmp_end))
3968 }
3969 // Parse ':'
3970 if (Tok.is(tok::colon))
3972 else
3973 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
3974 KindModifier = getOpenMPSimpleClauseType(
3975 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3976 }
3977 Arg[ScheduleKind] = KindModifier;
3978 KLoc[ScheduleKind] = Tok.getLocation();
3979 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3980 Tok.isNot(tok::annot_pragma_openmp_end))
3982 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3983 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3984 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3985 Tok.is(tok::comma))
3986 DelimLoc = ConsumeAnyToken();
3987 } else if (Kind == OMPC_dist_schedule) {
3988 Arg.push_back(getOpenMPSimpleClauseType(
3989 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3990 KLoc.push_back(Tok.getLocation());
3991 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3992 Tok.isNot(tok::annot_pragma_openmp_end))
3994 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
3995 DelimLoc = ConsumeAnyToken();
3996 } else if (Kind == OMPC_defaultmap) {
3997 // Get a defaultmap modifier
3998 unsigned Modifier = getOpenMPSimpleClauseType(
3999 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4000
4001 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
4002 // pointer
4003 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
4005 Arg.push_back(Modifier);
4006 KLoc.push_back(Tok.getLocation());
4007 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4008 Tok.isNot(tok::annot_pragma_openmp_end))
4010 // Parse ':'
4011 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
4012 if (Tok.is(tok::colon))
4014 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
4015 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
4016 // Get a defaultmap kind
4017 Arg.push_back(getOpenMPSimpleClauseType(
4018 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4019 KLoc.push_back(Tok.getLocation());
4020 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4021 Tok.isNot(tok::annot_pragma_openmp_end))
4023 } else {
4024 Arg.push_back(OMPC_DEFAULTMAP_unknown);
4025 KLoc.push_back(SourceLocation());
4026 }
4027 } else if (Kind == OMPC_order) {
4028 enum { Modifier, OrderKind, NumberOfElements };
4029 Arg.resize(NumberOfElements);
4030 KLoc.resize(NumberOfElements);
4031 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
4032 Arg[OrderKind] = OMPC_ORDER_unknown;
4033 unsigned KindModifier = getOpenMPSimpleClauseType(
4034 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4035 if (KindModifier > OMPC_ORDER_unknown) {
4036 // Parse 'modifier'
4037 Arg[Modifier] = KindModifier;
4038 KLoc[Modifier] = Tok.getLocation();
4039 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4040 Tok.isNot(tok::annot_pragma_openmp_end))
4042 // Parse ':'
4043 if (Tok.is(tok::colon))
4045 else
4046 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
4047 KindModifier = getOpenMPSimpleClauseType(
4048 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4049 }
4050 Arg[OrderKind] = KindModifier;
4051 KLoc[OrderKind] = Tok.getLocation();
4052 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4053 Tok.isNot(tok::annot_pragma_openmp_end))
4055 } else if (Kind == OMPC_device) {
4056 // Only target executable directives support extended device construct.
4057 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4058 NextToken().is(tok::colon)) {
4059 // Parse optional <device modifier> ':'
4060 Arg.push_back(getOpenMPSimpleClauseType(
4061 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4062 KLoc.push_back(Tok.getLocation());
4064 // Parse ':'
4066 } else {
4067 Arg.push_back(OMPC_DEVICE_unknown);
4068 KLoc.emplace_back();
4069 }
4070 } else if (Kind == OMPC_grainsize) {
4071 // Parse optional <grainsize modifier> ':'
4074 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4075 getLangOpts()));
4076 if (getLangOpts().OpenMP >= 51) {
4077 if (NextToken().is(tok::colon)) {
4078 Arg.push_back(Modifier);
4079 KLoc.push_back(Tok.getLocation());
4080 // Parse modifier
4082 // Parse ':'
4084 } else {
4085 if (Modifier == OMPC_GRAINSIZE_strict) {
4086 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4087 // Parse modifier
4089 }
4090 Arg.push_back(OMPC_GRAINSIZE_unknown);
4091 KLoc.emplace_back();
4092 }
4093 } else {
4094 Arg.push_back(OMPC_GRAINSIZE_unknown);
4095 KLoc.emplace_back();
4096 }
4097 } else if (Kind == OMPC_num_tasks) {
4098 // Parse optional <num_tasks modifier> ':'
4101 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4102 getLangOpts()));
4103 if (getLangOpts().OpenMP >= 51) {
4104 if (NextToken().is(tok::colon)) {
4105 Arg.push_back(Modifier);
4106 KLoc.push_back(Tok.getLocation());
4107 // Parse modifier
4109 // Parse ':'
4111 } else {
4112 if (Modifier == OMPC_NUMTASKS_strict) {
4113 Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4114 // Parse modifier
4116 }
4117 Arg.push_back(OMPC_NUMTASKS_unknown);
4118 KLoc.emplace_back();
4119 }
4120 } else {
4121 Arg.push_back(OMPC_NUMTASKS_unknown);
4122 KLoc.emplace_back();
4123 }
4124 } else {
4125 assert(Kind == OMPC_if);
4126 KLoc.push_back(Tok.getLocation());
4127 TentativeParsingAction TPA(*this);
4128 auto DK = parseOpenMPDirectiveKind(*this);
4129 Arg.push_back(DK);
4130 if (DK != OMPD_unknown) {
4131 ConsumeToken();
4132 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
4133 TPA.Commit();
4134 DelimLoc = ConsumeToken();
4135 } else {
4136 TPA.Revert();
4137 Arg.back() = unsigned(OMPD_unknown);
4138 }
4139 } else {
4140 TPA.Revert();
4141 }
4142 }
4143
4144 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4145 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
4146 Kind == OMPC_if || Kind == OMPC_device ||
4147 Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
4148 if (NeedAnExpression) {
4149 SourceLocation ELoc = Tok.getLocation();
4150 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
4151 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4152 Val =
4153 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
4154 }
4155
4156 // Parse ')'.
4157 SourceLocation RLoc = Tok.getLocation();
4158 if (!T.consumeClose())
4159 RLoc = T.getCloseLocation();
4160
4161 if (NeedAnExpression && Val.isInvalid())
4162 return nullptr;
4163
4164 if (ParseOnly)
4165 return nullptr;
4167 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4168}
4169
4170static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4171 UnqualifiedId &ReductionId) {
4172 if (ReductionIdScopeSpec.isEmpty()) {
4173 auto OOK = OO_None;
4174 switch (P.getCurToken().getKind()) {
4175 case tok::plus:
4176 OOK = OO_Plus;
4177 break;
4178 case tok::minus:
4179 OOK = OO_Minus;
4180 break;
4181 case tok::star:
4182 OOK = OO_Star;
4183 break;
4184 case tok::amp:
4185 OOK = OO_Amp;
4186 break;
4187 case tok::pipe:
4188 OOK = OO_Pipe;
4189 break;
4190 case tok::caret:
4191 OOK = OO_Caret;
4192 break;
4193 case tok::ampamp:
4194 OOK = OO_AmpAmp;
4195 break;
4196 case tok::pipepipe:
4197 OOK = OO_PipePipe;
4198 break;
4199 default:
4200 break;
4201 }
4202 if (OOK != OO_None) {
4203 SourceLocation OpLoc = P.ConsumeToken();
4204 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4205 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4206 return false;
4207 }
4208 }
4209 return P.ParseUnqualifiedId(
4210 ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4211 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4212 /*AllowDestructorName*/ false,
4213 /*AllowConstructorName*/ false,
4214 /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4215}
4216
4217/// Checks if the token is a valid map-type-modifier.
4218/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4220 Token Tok = P.getCurToken();
4221 if (!Tok.is(tok::identifier))
4223
4224 Preprocessor &PP = P.getPreprocessor();
4225 OpenMPMapModifierKind TypeModifier =
4227 OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4228 return TypeModifier;
4229}
4230
4231/// Parse the mapper modifier in map, to, and from clauses.
4233 // Parse '('.
4234 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4235 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4236 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4238 return true;
4239 }
4240 // Parse mapper-identifier
4241 if (getLangOpts().CPlusPlus)
4242 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4243 /*ObjectType=*/nullptr,
4244 /*ObjectHasErrors=*/false,
4245 /*EnteringContext=*/false);
4246 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4247 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4248 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4250 return true;
4251 }
4252 auto &DeclNames = Actions.getASTContext().DeclarationNames;
4253 Data.ReductionOrMapperId = DeclarationNameInfo(
4254 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4255 ConsumeToken();
4256 // Parse ')'.
4257 return T.consumeClose();
4258}
4259
4261
4262/// Parse map-type-modifiers in map clause.
4263/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] [map-type] : ] list)
4264/// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
4265/// present
4266/// where, map-type ::= alloc | delete | from | release | to | tofrom
4268 bool HasMapType = false;
4269 SourceLocation PreMapLoc = Tok.getLocation();
4270 StringRef PreMapName = "";
4271 while (getCurToken().isNot(tok::colon)) {
4272 OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4273 OpenMPMapClauseKind MapKind = isMapType(*this);
4274 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4275 TypeModifier == OMPC_MAP_MODIFIER_close ||
4276 TypeModifier == OMPC_MAP_MODIFIER_present ||
4277 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4278 Data.MapTypeModifiers.push_back(TypeModifier);
4279 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4280 if (PP.LookAhead(0).isNot(tok::comma) &&
4281 PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4282 Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4283 << "map type modifier";
4284 ConsumeToken();
4285 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4286 Data.MapTypeModifiers.push_back(TypeModifier);
4287 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4288 ConsumeToken();
4290 return true;
4291 if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4292 getLangOpts().OpenMP >= 52)
4293 Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4294 << "map type modifier";
4295
4296 } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4297 if (!HasMapType) {
4298 HasMapType = true;
4299 Data.ExtraModifier = MapKind;
4300 MapKind = OMPC_MAP_unknown;
4301 PreMapLoc = Tok.getLocation();
4302 PreMapName = Tok.getIdentifierInfo()->getName();
4303 } else {
4304 Diag(Tok, diag::err_omp_more_one_map_type);
4305 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4306 << PreMapName;
4307 }
4308 ConsumeToken();
4309 } else {
4310 // For the case of unknown map-type-modifier or a map-type.
4311 // Map-type is followed by a colon; the function returns when it
4312 // encounters a token followed by a colon.
4313 if (Tok.is(tok::comma)) {
4314 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4315 ConsumeToken();
4316 continue;
4317 }
4318 // Potential map-type token as it is followed by a colon.
4319 if (PP.LookAhead(0).is(tok::colon)) {
4320 if (getLangOpts().OpenMP >= 60) {
4321 break;
4322 } else {
4323 return false;
4324 }
4325 }
4326
4327 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4328 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4329 : 0)
4330 << getLangOpts().OpenMPExtensions;
4331 ConsumeToken();
4332 }
4333 if (getCurToken().is(tok::comma))
4334 ConsumeToken();
4335 }
4336 if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4337 if (!Tok.is(tok::colon)) {
4338 Diag(Tok, diag::err_omp_unknown_map_type);
4339 ConsumeToken();
4340 } else {
4341 Data.ExtraModifier = OMPC_MAP_unknown;
4342 }
4343 }
4344 return false;
4345}
4346
4347/// Checks if the token is a valid map-type.
4348/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4350 Token Tok = P.getCurToken();
4351 // The map-type token can be either an identifier or the C++ delete keyword.
4352 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4353 return OMPC_MAP_unknown;
4354 Preprocessor &PP = P.getPreprocessor();
4355 unsigned MapType =
4356 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok), P.getLangOpts());
4357 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4358 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4359 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4360 return static_cast<OpenMPMapClauseKind>(MapType);
4361 return OMPC_MAP_unknown;
4362}
4363
4364/// Parse map-type in map clause.
4365/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4366/// where, map-type ::= to | from | tofrom | alloc | release | delete
4368 Token Tok = P.getCurToken();
4369 if (Tok.is(tok::colon)) {
4370 P.Diag(Tok, diag::err_omp_map_type_missing);
4371 return;
4372 }
4373 Data.ExtraModifier = isMapType(P);
4374 if (Data.ExtraModifier == OMPC_MAP_unknown)
4375 P.Diag(Tok, diag::err_omp_unknown_map_type);
4376 P.ConsumeToken();
4377}
4378
4379/// Parses simple expression in parens for single-expression clauses of OpenMP
4380/// constructs.
4381ExprResult Parser::ParseOpenMPIteratorsExpr() {
4382 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4383 "Expected 'iterator' token.");
4384 SourceLocation IteratorKwLoc = ConsumeToken();
4385
4386 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4387 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4388 return ExprError();
4389
4390 SourceLocation LLoc = T.getOpenLocation();
4392 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4393 // Check if the type parsing is required.
4394 ParsedType IteratorType;
4395 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4396 // identifier '=' is not found - parse type.
4398 if (TR.isInvalid()) {
4399 T.skipToEnd();
4400 return ExprError();
4401 }
4402 IteratorType = TR.get();
4403 }
4404
4405 // Parse identifier.
4406 IdentifierInfo *II = nullptr;
4407 SourceLocation IdLoc;
4408 if (Tok.is(tok::identifier)) {
4409 II = Tok.getIdentifierInfo();
4410 IdLoc = ConsumeToken();
4411 } else {
4412 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4413 }
4414
4415 // Parse '='.
4416 SourceLocation AssignLoc;
4417 if (Tok.is(tok::equal))
4418 AssignLoc = ConsumeToken();
4419 else
4420 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4421
4422 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4423 ColonProtectionRAIIObject ColonRAII(*this);
4424 // Parse <begin>
4426 ExprResult LHS = ParseCastExpression(AnyCastExpr);
4428 ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4429 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4430 /*DiscardedValue=*/false);
4431 // Parse ':'.
4432 SourceLocation ColonLoc;
4433 if (Tok.is(tok::colon))
4434 ColonLoc = ConsumeToken();
4435
4436 // Parse <end>
4437 Loc = Tok.getLocation();
4438 LHS = ParseCastExpression(AnyCastExpr);
4440 ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4441 End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4442 /*DiscardedValue=*/false);
4443
4444 SourceLocation SecColonLoc;
4445 ExprResult Step;
4446 // Parse optional step.
4447 if (Tok.is(tok::colon)) {
4448 // Parse ':'
4449 SecColonLoc = ConsumeToken();
4450 // Parse <step>
4451 Loc = Tok.getLocation();
4452 LHS = ParseCastExpression(AnyCastExpr);
4453 Step = Actions.CorrectDelayedTyposInExpr(
4454 ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4455 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4456 /*DiscardedValue=*/false);
4457 }
4458
4459 // Parse ',' or ')'
4460 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4461 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4462 if (Tok.is(tok::comma))
4463 ConsumeToken();
4464
4465 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4466 D.DeclIdent = II;
4467 D.DeclIdentLoc = IdLoc;
4468 D.Type = IteratorType;
4469 D.AssignLoc = AssignLoc;
4470 D.ColonLoc = ColonLoc;
4471 D.SecColonLoc = SecColonLoc;
4472 D.Range.Begin = Begin.get();
4473 D.Range.End = End.get();
4474 D.Range.Step = Step.get();
4475 }
4476
4477 // Parse ')'.
4478 SourceLocation RLoc = Tok.getLocation();
4479 if (!T.consumeClose())
4480 RLoc = T.getCloseLocation();
4481
4482 return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4483 LLoc, RLoc, Data);
4484}
4485
4488 const LangOptions &LangOpts) {
4489 // Currently the only reserved locator is 'omp_all_memory' which is only
4490 // allowed on a depend clause.
4491 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4492 return false;
4493
4494 if (Tok.is(tok::identifier) &&
4495 Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4496
4497 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4498 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4499 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4500 else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4501 Data.ExtraModifier != OMPC_DEPEND_inout)
4502 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4503 else
4504 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4505 ? OMPC_DEPEND_outallmemory
4506 : OMPC_DEPEND_inoutallmemory;
4507 ConsumeToken();
4508 return true;
4509 }
4510 return false;
4511}
4512
4513/// Parse step size expression. Returns true if parsing is successfull,
4514/// otherwise returns false.
4516 OpenMPClauseKind CKind, SourceLocation ELoc) {
4517 ExprResult Tail = P.ParseAssignmentExpression();
4518 Sema &Actions = P.getActions();
4519 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4520 /*DiscardedValue*/ false);
4521 if (Tail.isUsable()) {
4522 Data.DepModOrTailExpr = Tail.get();
4523 Token CurTok = P.getCurToken();
4524 if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
4525 P.Diag(CurTok, diag::err_expected_punc) << "step expression";
4526 }
4527 return true;
4528 }
4529 return false;
4530}
4531
4532/// Parse 'allocate' clause modifiers.
4533/// If allocator-modifier exists, return an expression for it and set
4534/// Data field noting modifier was specified.
4535///
4536static ExprResult
4539 const Token &Tok = P.getCurToken();
4540 Preprocessor &PP = P.getPreprocessor();
4541 ExprResult Tail;
4542 auto Modifier = static_cast<OpenMPAllocateClauseModifier>(
4543 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));
4544 if (Modifier == OMPC_ALLOCATE_allocator) {
4545 Data.AllocClauseModifier = Modifier;
4546 P.ConsumeToken();
4547 BalancedDelimiterTracker AllocateT(P, tok::l_paren,
4548 tok::annot_pragma_openmp_end);
4549 if (Tok.is(tok::l_paren)) {
4550 AllocateT.consumeOpen();
4551 Tail = P.ParseAssignmentExpression();
4552 AllocateT.consumeClose();
4553 } else {
4554 P.Diag(Tok, diag::err_expected) << tok::l_paren;
4555 }
4556 } else {
4557 Tail = P.ParseAssignmentExpression();
4558 }
4559 return Tail;
4560}
4561
4562/// Parses clauses with list.
4564 OpenMPClauseKind Kind,
4567 UnqualifiedId UnqualifiedReductionId;
4568 bool InvalidReductionId = false;
4569 bool IsInvalidMapperModifier = false;
4570
4571 // Parse '('.
4572 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4573 if (T.expectAndConsume(diag::err_expected_lparen_after,
4574 getOpenMPClauseName(Kind).data()))
4575 return true;
4576
4577 bool HasIterator = false;
4578 bool InvalidIterator = false;
4579 bool NeedRParenForLinear = false;
4580 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4581 tok::annot_pragma_openmp_end);
4582 // Handle reduction-identifier for reduction clause.
4583 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4584 Kind == OMPC_in_reduction) {
4585 Data.ExtraModifier = OMPC_REDUCTION_unknown;
4586 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4587 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
4588 NextToken().is(tok::comma)) {
4589 // Parse optional reduction modifier.
4590 Data.ExtraModifier =
4592 Data.ExtraModifierLoc = Tok.getLocation();
4593 ConsumeToken();
4594 assert(Tok.is(tok::comma) && "Expected comma.");
4595 (void)ConsumeToken();
4596 }
4597 ColonProtectionRAIIObject ColonRAII(*this);
4598 if (getLangOpts().CPlusPlus)
4599 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4600 /*ObjectType=*/nullptr,
4601 /*ObjectHasErrors=*/false,
4602 /*EnteringContext=*/false);
4603 InvalidReductionId = ParseReductionId(
4604 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4605 if (InvalidReductionId) {
4606 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4608 }
4609 if (Tok.is(tok::colon))
4610 Data.ColonLoc = ConsumeToken();
4611 else
4612 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
4613 if (!InvalidReductionId)
4614 Data.ReductionOrMapperId =
4615 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
4616 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4617 if (getLangOpts().OpenMP >= 50) {
4618 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4619 // Handle optional dependence modifier.
4620 // iterator(iterators-definition)
4621 // where iterators-definition is iterator-specifier [,
4622 // iterators-definition ]
4623 // where iterator-specifier is [ iterator-type ] identifier =
4624 // range-specification
4625 HasIterator = true;
4627 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4628 Data.DepModOrTailExpr = IteratorRes.get();
4629 // Parse ','
4630 ExpectAndConsume(tok::comma);
4631 }
4632 }
4633 // Handle dependency type for depend clause.
4634 ColonProtectionRAIIObject ColonRAII(*this);
4635 Data.ExtraModifier = getOpenMPSimpleClauseType(
4636 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4637 getLangOpts());
4638 Data.ExtraModifierLoc = Tok.getLocation();
4639 if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
4640 (Kind == OMPC_doacross &&
4641 Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
4642 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4644 } else {
4645 ConsumeToken();
4646 // Special processing for depend(source) clause.
4647 if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4648 Data.ExtraModifier == OMPC_DEPEND_source) {
4649 // Parse ')'.
4650 T.consumeClose();
4651 return false;
4652 }
4653 }
4654 if (Tok.is(tok::colon)) {
4655 Data.ColonLoc = ConsumeToken();
4656 } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
4657 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4658 : diag::warn_pragma_expected_colon)
4659 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
4660 }
4661 if (Kind == OMPC_doacross) {
4662 if (Tok.is(tok::identifier) &&
4663 Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
4664 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
4665 ? OMPC_DOACROSS_source_omp_cur_iteration
4666 : OMPC_DOACROSS_sink_omp_cur_iteration;
4667 ConsumeToken();
4668 }
4669 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
4670 if (Tok.isNot(tok::minus)) {
4671 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4672 << getOpenMPClauseName(Kind) << 0 << 0;
4673 SkipUntil(tok::r_paren);
4674 return false;
4675 } else {
4676 ConsumeToken();
4678 uint64_t Value = 0;
4679 if (Tok.isNot(tok::numeric_constant) ||
4680 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
4681 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
4682 << getOpenMPClauseName(Kind) << 0 << 0;
4683 SkipUntil(tok::r_paren);
4684 return false;
4685 }
4686 }
4687 }
4688 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
4689 if (Tok.isNot(tok::r_paren)) {
4690 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4691 << getOpenMPClauseName(Kind) << 1 << 1;
4692 SkipUntil(tok::r_paren);
4693 return false;
4694 }
4695 }
4696 // Only the 'sink' case has the expression list.
4697 if (Kind == OMPC_doacross &&
4698 (Data.ExtraModifier == OMPC_DOACROSS_source ||
4699 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
4700 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
4701 // Parse ')'.
4702 T.consumeClose();
4703 return false;
4704 }
4705 }
4706 } else if (Kind == OMPC_linear) {
4707 // Try to parse modifier if any.
4708 Data.ExtraModifier = OMPC_LINEAR_val;
4709 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
4710 Data.ExtraModifier =
4712 Data.ExtraModifierLoc = ConsumeToken();
4713 LinearT.consumeOpen();
4714 NeedRParenForLinear = true;
4715 if (getLangOpts().OpenMP >= 52)
4716 Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
4717 << "linear-modifier(list)" << getOpenMPClauseName(Kind)
4718 << "linear(list: [linear-modifier,] step(step-size))";
4719 }
4720 } else if (Kind == OMPC_lastprivate) {
4721 // Try to parse modifier if any.
4722 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
4723 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
4724 // distribute and taskloop based directives.
4725 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
4726 !isOpenMPTaskLoopDirective(DKind)) &&
4727 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
4728 Data.ExtraModifier =
4730 Data.ExtraModifierLoc = Tok.getLocation();
4731 ConsumeToken();
4732 assert(Tok.is(tok::colon) && "Expected colon.");
4733 Data.ColonLoc = ConsumeToken();
4734 }
4735 } else if (Kind == OMPC_map) {
4736 // Handle optional iterator map modifier.
4737 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4738 HasIterator = true;
4740 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4741 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4742 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4743 Data.IteratorExpr = IteratorRes.get();
4744 // Parse ','
4745 ExpectAndConsume(tok::comma);
4746 if (getLangOpts().OpenMP < 52) {
4747 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4748 << (getLangOpts().OpenMP >= 51 ? 1 : 0)
4749 << getLangOpts().OpenMPExtensions;
4750 InvalidIterator = true;
4751 }
4752 }
4753 // Handle map type for map clause.
4754 ColonProtectionRAIIObject ColonRAII(*this);
4755
4756 // The first identifier may be a list item, a map-type or a
4757 // map-type-modifier. The map-type can also be delete which has the same
4758 // spelling of the C++ delete keyword.
4759 Data.ExtraModifier = OMPC_MAP_unknown;
4760 Data.ExtraModifierLoc = Tok.getLocation();
4761
4762 // Check for presence of a colon in the map clause.
4763 TentativeParsingAction TPA(*this);
4764 bool ColonPresent = false;
4765 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4766 StopBeforeMatch)) {
4767 if (Tok.is(tok::colon))
4768 ColonPresent = true;
4769 }
4770 TPA.Revert();
4771 // Only parse map-type-modifier[s] and map-type if a colon is present in
4772 // the map clause.
4773 if (ColonPresent) {
4774 if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
4775 Diag(Tok, diag::err_omp_map_modifier_specification_list);
4776 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
4777 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
4778 parseMapType(*this, Data);
4779 else
4780 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
4781 }
4782 if (Data.ExtraModifier == OMPC_MAP_unknown) {
4783 Data.ExtraModifier = OMPC_MAP_tofrom;
4784 if (getLangOpts().OpenMP >= 52) {
4785 if (DKind == OMPD_target_enter_data)
4786 Data.ExtraModifier = OMPC_MAP_to;
4787 else if (DKind == OMPD_target_exit_data)
4788 Data.ExtraModifier = OMPC_MAP_from;
4789 }
4790 Data.IsMapTypeImplicit = true;
4791 }
4792
4793 if (Tok.is(tok::colon))
4794 Data.ColonLoc = ConsumeToken();
4795 } else if (Kind == OMPC_to || Kind == OMPC_from) {
4796 while (Tok.is(tok::identifier)) {
4797 auto Modifier = static_cast<OpenMPMotionModifierKind>(
4799 if (Modifier == OMPC_MOTION_MODIFIER_unknown)
4800 break;
4801 Data.MotionModifiers.push_back(Modifier);
4802 Data.MotionModifiersLoc.push_back(Tok.getLocation());
4803 ConsumeToken();
4804 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
4805 IsInvalidMapperModifier = parseMapperModifier(Data);
4806 if (IsInvalidMapperModifier)
4807 break;
4808 }
4809 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
4810 if (getLangOpts().OpenMP < 51)
4811 break;
4812 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
4813 // TODO: Is that intentional?
4814 if (Tok.is(tok::comma))
4815 ConsumeToken();
4816 }
4817 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
4818 if (!IsInvalidMapperModifier) {
4819 if (getLangOpts().OpenMP < 51)
4820 Diag(Tok, diag::warn_pragma_expected_colon) << ")";
4821 else
4822 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
4823 }
4824 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4826 }
4827 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
4828 // that intentional?
4829 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
4830 Tok.is(tok::colon))
4831 Data.ColonLoc = ConsumeToken();
4832 } else if (Kind == OMPC_allocate ||
4833 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
4834 PP.getSpelling(Tok) == "iterator")) {
4835 // Handle optional allocator expression followed by colon delimiter.
4836 ColonProtectionRAIIObject ColonRAII(*this);
4837 TentativeParsingAction TPA(*this);
4838 // OpenMP 5.0, 2.10.1, task Construct.
4839 // where aff-modifier is one of the following:
4840 // iterator(iterators-definition)
4841 ExprResult Tail;
4842 if (Kind == OMPC_allocate) {
4843 Tail = parseOpenMPAllocateClauseModifiers(*this, Kind, Data);
4844 } else {
4845 HasIterator = true;
4847 Tail = ParseOpenMPIteratorsExpr();
4848 }
4849 Tail = Actions.CorrectDelayedTyposInExpr(Tail);
4850 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
4851 /*DiscardedValue=*/false);
4852 if (Tail.isUsable()) {
4853 if (Tok.is(tok::colon)) {
4854 Data.DepModOrTailExpr = Tail.get();
4855 Data.ColonLoc = ConsumeToken();
4856 TPA.Commit();
4857 } else {
4858 // Colon not found, parse only list of variables.
4859 TPA.Revert();
4860 if (Kind == OMPC_allocate &&
4861 Data.AllocClauseModifier == OMPC_ALLOCATE_allocator) {
4862 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
4864 Diag(Tok, diag::err_modifier_expected_colon) << "allocator";
4865 }
4866 }
4867 } else {
4868 // Parsing was unsuccessfull, revert and skip to the end of clause or
4869 // directive.
4870 TPA.Revert();
4871 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4873 }
4874 } else if (Kind == OMPC_adjust_args) {
4875 // Handle adjust-op for adjust_args clause.
4876 ColonProtectionRAIIObject ColonRAII(*this);
4877 Data.ExtraModifier = getOpenMPSimpleClauseType(
4878 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4879 getLangOpts());
4880 Data.ExtraModifierLoc = Tok.getLocation();
4881 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
4882 Diag(Tok, diag::err_omp_unknown_adjust_args_op);
4883 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
4884 } else {
4885 ConsumeToken();
4886 if (Tok.is(tok::colon))
4887 Data.ColonLoc = Tok.getLocation();
4888 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
4889 "adjust-op");
4890 }
4891 }
4892
4893 bool IsComma =
4894 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
4895 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
4896 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
4897 (Kind == OMPC_reduction && !InvalidReductionId) ||
4898 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
4899 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
4900 (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
4901 (Kind == OMPC_adjust_args &&
4902 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
4903 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
4904 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
4905 Tok.isNot(tok::annot_pragma_openmp_end))) {
4906 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
4907 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
4909 // Parse variable
4910 ExprResult VarExpr =
4912 if (VarExpr.isUsable()) {
4913 Vars.push_back(VarExpr.get());
4914 } else {
4915 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4917 }
4918 }
4919 // Skip ',' if any
4920 IsComma = Tok.is(tok::comma);
4921 if (IsComma)
4922 ConsumeToken();
4923 else if (Tok.isNot(tok::r_paren) &&
4924 Tok.isNot(tok::annot_pragma_openmp_end) &&
4925 (!MayHaveTail || Tok.isNot(tok::colon)))
4926 Diag(Tok, diag::err_omp_expected_punc)
4927 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
4928 : getOpenMPClauseName(Kind))
4929 << (Kind == OMPC_flush);
4930 }
4931
4932 // Parse ')' for linear clause with modifier.
4933 if (NeedRParenForLinear)
4934 LinearT.consumeClose();
4935 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
4936 // or parse ':' alignment.
4937 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
4938 bool StepFound = false;
4939 bool ModifierFound = false;
4940 if (MustHaveTail) {
4941 Data.ColonLoc = Tok.getLocation();
4943
4944 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
4945 while (Tok.isNot(tok::r_paren)) {
4946 if (Tok.is(tok::identifier)) {
4947 // identifier could be a linear kind (val, uval, ref) or step
4948 // modifier or step size
4949 OpenMPLinearClauseKind LinKind =
4951 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4952 getLangOpts()));
4953
4954 if (LinKind == OMPC_LINEAR_step) {
4955 if (StepFound)
4956 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
4957
4958 BalancedDelimiterTracker StepT(*this, tok::l_paren,
4959 tok::annot_pragma_openmp_end);
4960 SourceLocation StepModifierLoc = ConsumeToken();
4961 // parse '('
4962 if (StepT.consumeOpen())
4963 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
4964
4965 // parse step size expression
4966 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4967 if (StepFound)
4968 Data.StepModifierLoc = StepModifierLoc;
4969
4970 // parse ')'
4971 StepT.consumeClose();
4972 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
4973 if (ModifierFound)
4974 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
4975
4976 Data.ExtraModifier = LinKind;
4977 Data.ExtraModifierLoc = ConsumeToken();
4978 ModifierFound = true;
4979 } else {
4980 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4981 }
4982 } else {
4983 // parse an integer expression as step size
4984 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4985 }
4986
4987 if (Tok.is(tok::comma))
4988 ConsumeToken();
4989 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
4990 break;
4991 }
4992 if (!StepFound && !ModifierFound)
4993 Diag(ELoc, diag::err_expected_expression);
4994 } else {
4995 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
4997 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4998 /*DiscardedValue*/ false);
4999 if (Tail.isUsable())
5000 Data.DepModOrTailExpr = Tail.get();
5001 else
5002 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
5004 }
5005 }
5006
5007 // Parse ')'.
5008 Data.RLoc = Tok.getLocation();
5009 if (!T.consumeClose())
5010 Data.RLoc = T.getCloseLocation();
5011 // Exit from scope when the iterator is used in depend clause.
5012 if (HasIterator)
5013 ExitScope();
5014 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
5015 Vars.empty()) ||
5016 (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
5017 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
5018}
5019
5020/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
5021/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
5022/// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
5023///
5024/// private-clause:
5025/// 'private' '(' list ')'
5026/// firstprivate-clause:
5027/// 'firstprivate' '(' list ')'
5028/// lastprivate-clause:
5029/// 'lastprivate' '(' list ')'
5030/// shared-clause:
5031/// 'shared' '(' list ')'
5032/// linear-clause:
5033/// 'linear' '(' linear-list [ ':' linear-step ] ')'
5034/// aligned-clause:
5035/// 'aligned' '(' list [ ':' alignment ] ')'
5036/// reduction-clause:
5037/// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
5038/// task_reduction-clause:
5039/// 'task_reduction' '(' reduction-identifier ':' list ')'
5040/// in_reduction-clause:
5041/// 'in_reduction' '(' reduction-identifier ':' list ')'
5042/// copyprivate-clause:
5043/// 'copyprivate' '(' list ')'
5044/// flush-clause:
5045/// 'flush' '(' list ')'
5046/// depend-clause:
5047/// 'depend' '(' in | out | inout : list | source ')'
5048/// map-clause:
5049/// 'map' '(' [ [ always [,] ] [ close [,] ]
5050/// [ mapper '(' mapper-identifier ')' [,] ]
5051/// to | from | tofrom | alloc | release | delete ':' ] list ')';
5052/// to-clause:
5053/// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
5054/// from-clause:
5055/// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
5056/// use_device_ptr-clause:
5057/// 'use_device_ptr' '(' list ')'
5058/// use_device_addr-clause:
5059/// 'use_device_addr' '(' list ')'
5060/// is_device_ptr-clause:
5061/// 'is_device_ptr' '(' list ')'
5062/// has_device_addr-clause:
5063/// 'has_device_addr' '(' list ')'
5064/// allocate-clause:
5065/// 'allocate' '(' [ allocator ':' ] list ')'
5066/// As of OpenMP 5.1 there's also
5067/// 'allocate' '(' allocate-modifier: list ')'
5068/// where allocate-modifier is: 'allocator' '(' allocator ')'
5069/// nontemporal-clause:
5070/// 'nontemporal' '(' list ')'
5071/// inclusive-clause:
5072/// 'inclusive' '(' list ')'
5073/// exclusive-clause:
5074/// 'exclusive' '(' list ')'
5075///
5076/// For 'linear' clause linear-list may have the following forms:
5077/// list
5078/// modifier(list)
5079/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
5080OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5081 OpenMPClauseKind Kind,
5082 bool ParseOnly) {
5084 SourceLocation LOpen = ConsumeToken();
5087
5088 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
5089 return nullptr;
5090
5091 if (ParseOnly)
5092 return nullptr;
5093 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5094 return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5095}
5096
5097bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5098 SourceLocation &ClauseNameLoc,
5099 SourceLocation &OpenLoc,
5100 SourceLocation &CloseLoc,
5102 bool ReqIntConst) {
5103 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5104 "Expected parsing to start at clause name");
5105 ClauseNameLoc = ConsumeToken();
5106
5107 // Parse inside of '(' and ')'.
5108 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5109 if (T.consumeOpen()) {
5110 Diag(Tok, diag::err_expected) << tok::l_paren;
5111 return true;
5112 }
5113
5114 // Parse the list with interleaved commas.
5115 do {
5116 ExprResult Val =
5118 if (!Val.isUsable()) {
5119 // Encountered something other than an expression; abort to ')'.
5120 T.skipToEnd();
5121 return true;
5122 }
5123 Exprs.push_back(Val.get());
5124 } while (TryConsumeToken(tok::comma));
5125
5126 bool Result = T.consumeClose();
5127 OpenLoc = T.getOpenLocation();
5128 CloseLoc = T.getCloseLocation();
5129 return Result;
5130}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3443
StringRef P
const Decl * D
Expr * E
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P)
static OpenMPMapModifierKind isMapModifier(Parser &P)
Checks if the token is a valid map-type-modifier.
static std::optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)
static unsigned getOpenMPDirectiveKindEx(StringRef S)
static bool checkExtensionProperty(Parser &P, SourceLocation Loc, OMPTraitProperty &TIProperty, OMPTraitSelector &TISelector, llvm::StringMap< SourceLocation > &Seen)
static ExprResult parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse 'allocate' clause modifiers.
static DeclarationName parseOpenMPReductionId(Parser &P)
static ExprResult parseContextScore(Parser &P)
Parse optional 'score' '(' <expr> ')' ':'.
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, OpenMPClauseKind CKind, SourceLocation ELoc)
Parse step size expression.
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
static bool 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)
Parses clauses for 'declare simd' directive.
static OpenMPMapClauseKind isMapType(Parser &P)
Checks if the token is a valid map-type.
This file declares semantic analysis functions specific to AMDGPU.
This file declares facilities that support code completion.
SourceRange Range
Definition: SemaObjC.cpp:758
SourceLocation Loc
Definition: SemaObjC.cpp:759
This file declares semantic analysis for OpenMP constructs and clauses.
This file defines OpenMP AST classes for executable directives and clauses.
Defines the clang::TokenKind enum and support functions.
SourceLocation Begin
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:684
IdentifierTable & Idents
Definition: ASTContext.h:680
OMPTraitInfo & getNewOMPTraitInfo()
Return a new OMPTraitInfo object owned by this context.
bool isUnset() const
Definition: Ownership.h:167
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
bool isEmpty() const
No scope specifier.
Definition: DeclSpec.h:208
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed.
Captures information about "declaration specifiers".
Definition: DeclSpec.h:247