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
static const TST TST_unspecified
Definition: DeclSpec.h:278
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition: DeclBase.h:1108
SourceLocation getLocation() const
Definition: DeclBase.h:442
DeclContext * getDeclContext()
Definition: DeclBase.h:451
The name of a declaration.
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1903
RAII object that enters a new expression evaluation context.
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition: Expr.h:239
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:499
This represents a decl that may have a name.
Definition: Decl.h:253
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition: Decl.cpp:1951
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
llvm::SmallVector< OMPTraitSet, 2 > Sets
The outermost level of selector sets.
Wrapper for void* pointer.
Definition: Ownership.h:50
PtrTy get() const
Definition: Ownership.h:80
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing,...
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
static const ParsedAttributesView & none()
Definition: ParsedAttr.h:836
ParsedAttributes - A collection of parsed attributes.
Definition: ParsedAttr.h:956
Introduces zero or more scopes for parsing.
Definition: Parser.h:1209
ParseScope - Introduces a new scope for parsing.
Definition: Parser.h:1171
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:58
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, SemaOpenMP::OpenMPVarListDataTy &Data)
Parses clauses with list.
TypeResult ParseTypeName(SourceRange *Range=nullptr, DeclaratorContext Context=DeclaratorContext::TypeName, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)
ParseTypeName type-name: [C99 6.7.6] specifier-qualifier-list abstract-declarator[opt].
Definition: ParseDecl.cpp:50
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Definition: Parser.cpp:81
bool parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses map-type-modifiers in map clause.
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
Definition: Parser.h:548
void EnterScope(unsigned ScopeFlags)
EnterScope - Start a new scope.
Definition: Parser.cpp:420
bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
bool ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
Definition: Parser.h:576
ExprResult ParseConstantExpression()
Definition: ParseExpr.cpp:235
bool TryConsumeToken(tok::TokenKind Expected)
Definition: Parser.h:556
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition: Parser.h:513
Scope * getCurScope() const
Definition: Parser.h:502
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
Definition: Parser.h:1294
const Token & getCurToken() const
Definition: Parser.h:501
void ExitScope()
ExitScope - Pop a scope off the scope stack.
Definition: Parser.cpp:431
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
Definition: ParseExpr.cpp:171
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
const LangOptions & getLangOpts() const
Definition: Parser.h:495
ExprResult ParseExpression(TypeCastState isTypeCast=NotTypeCast)
Simple precedence-based parser for binary/ternary operators.
Definition: ParseExpr.cpp:134
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
Definition: Parser.h:1275
bool ParseOpenMPReservedLocator(OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data, const LangOptions &LangOpts)
Parses a reserved locator like 'omp_all_memory'.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
Definition: Parser.h:872
A class for parsing a DeclSpec.
Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.
void enterVariableInit(SourceLocation Tok, Decl *D)
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:138
void EnterToken(const Token &Tok, bool IsReinject)
Enters a token in the token stream to be lexed next.
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value)
Parses a simple integer literal to get its numeric value.
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool isCodeCompletionReached() const
Returns true if code-completion is enabled and we have hit the code-completion point.
A (possibly-)qualified type.
Definition: Type.h:929
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:996
The collection of all-type qualifiers we support.
Definition: Type.h:324
Represents a struct/union/class.
Definition: Decl.h:4148
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
@ OpenMPDirectiveScope
This is the scope of OpenMP executable directive.
Definition: Scope.h:111
@ CompoundStmtScope
This is a compound statement scope.
Definition: Scope.h:134
@ OpenMPSimdDirectiveScope
This is the scope of some OpenMP simd directive.
Definition: Scope.h:119
@ FnScope
This indicates that the scope corresponds to a function, which means that labels are set here.
Definition: Scope.h:51
@ OpenMPLoopDirectiveScope
This is the scope of some OpenMP loop directive.
Definition: Scope.h:114
@ DeclScope
This is a scope that can contain a declaration.
Definition: Scope.h:63
Smart pointer class that efficiently represents Objective-C method names.
AMDGPUWavesPerEUAttr * CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
Definition: SemaAMDGPU.cpp:262
AMDGPUFlatWorkGroupSizeAttr * CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
Definition: SemaAMDGPU.cpp:201
QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, ArrayRef< Expr * > Args, SourceLocation OpenParLoc, bool Braced)
void CodeCompleteInitializer(Scope *S, Decl *D)
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition: SemaOpenMP.h:111
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
Definition: SemaOpenMP.h:243
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition: SemaOpenMP.h:371
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition: Sema.h:8041
A RAII object to enter scope of a compound statement.
Definition: Sema.h:915
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:463
SemaAMDGPU & AMDGPU()
Definition: Sema.h:1045
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:731
SemaOpenMP & OpenMP()
Definition: Sema.h:1125
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
Definition: SemaExpr.cpp:20371
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
Definition: SemaExpr.cpp:17138
void ActOnReenterFunctionContext(Scope *S, Decl *D)
Push the parameters of D, which must be a function, into scope.
Definition: SemaDecl.cpp:1431
void FinalizeDeclaration(Decl *D)
FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform any semantic actions neces...
Definition: SemaDecl.cpp:14677
DeclarationNameInfo GetNameForDeclarator(Declarator &D)
GetNameForDeclarator - Determine the full declaration name for the given Declarator.
Definition: SemaDecl.cpp:5782
@ AllowFold
Definition: Sema.h:7238
ASTContext & getASTContext() const
Definition: Sema.h:531
ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val)
Definition: SemaExpr.cpp:7915
SemaCodeCompletion & CodeCompletion()
Definition: Sema.h:1065
DeclContext * getCurLexicalContext() const
Definition: Sema.h:735
DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef< Decl * > Group)
BuildDeclaratorGroup - convert a list of declarations into a declaration group, performing any necess...
Definition: SemaDecl.cpp:14909
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)
Retrieves the declaration name from a parsed unqualified-id.
Definition: SemaDecl.cpp:5787
void ActOnInitializerError(Decl *Dcl)
ActOnInitializerError - Given that there was an error parsing an initializer for the given declaratio...
Definition: SemaDecl.cpp:13903
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:76
void ActOnUninitializedDecl(Decl *dcl)
Definition: SemaDecl.cpp:13945
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13386
CUDALaunchBoundsAttr * CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks)
Create an CUDALaunchBoundsAttr attribute.
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:451
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:8261
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1778
Token - This structure provides full information about a lexed token.
Definition: Token.h:36
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:187
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
Definition: Token.h:110
SourceLocation getEndLoc() const
Definition: Token.h:159
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition: Token.h:132
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition: Token.h:99
tok::TokenKind getKind() const
Definition: Token.h:94
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
Definition: Token.h:101
bool isNot(tok::TokenKind K) const
Definition: Token.h:100
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Definition: Token.h:121
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
The base class of the type hierarchy.
Definition: Type.h:1828
QualType getCanonicalTypeInternal() const
Definition: Type.h:2989
Represents a C++ unqualified-id that has been parsed.
Definition: DeclSpec.h:1028
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
Definition: DeclSpec.cpp:1510
QualType getType() const
Definition: Decl.h:682
Represents a variable declaration or definition.
Definition: Decl.h:882
Directive - Abstract class representing a parsed verify directive.
Defines the clang::TargetInfo interface.
bool Ret(InterpState &S, CodePtr &PC)
Definition: Interp.h:318
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
Definition: TokenKinds.h:89
The JSON file list parser is used to communicate input to InstallAPI.
TypeSpecifierType
Specifies the kind of type.
Definition: Specifiers.h:55
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
@ CPlusPlus
Definition: LangStandard.h:55
@ CPlusPlus11
Definition: LangStandard.h:56
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:25
@ OMPC_DEFAULTMAP_MODIFIER_unknown
Definition: OpenMPKinds.h:120
@ OMPC_ORDER_MODIFIER_unknown
Definition: OpenMPKinds.h:173
@ OMPC_ADJUST_ARGS_unknown
Definition: OpenMPKinds.h:197
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ OMPC_REDUCTION_unknown
Definition: OpenMPKinds.h:190
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition: CallGraph.h:204
OpenMPDeviceType
OpenMP device type for 'device_type' clause.
Definition: OpenMPKinds.h:150
@ OMPC_DEVICE_TYPE_unknown
Definition: OpenMPKinds.h:154
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition: OpenMPKinds.h:40
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:28
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ OMPC_DOACROSS_unknown
Definition: OpenMPKinds.h:223
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
StmtResult StmtError()
Definition: Ownership.h:265
DeclaratorContext
Definition: DeclSpec.h:1853
@ Property
The type of a property.
@ Result
The result type of a method or function.
@ OMPC_LASTPRIVATE_unknown
Definition: OpenMPKinds.h:161
@ OMPC_DEPEND_unknown
Definition: OpenMPKinds.h:59
OpenMPGrainsizeClauseModifier
Definition: OpenMPKinds.h:207
@ OMPC_GRAINSIZE_unknown
Definition: OpenMPKinds.h:210
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts)
OpenMPNumTasksClauseModifier
Definition: OpenMPKinds.h:213
@ OMPC_NUMTASKS_unknown
Definition: OpenMPKinds.h:216
ActionResult< Expr * > ExprResult
Definition: Ownership.h:248
ExprResult ExprError()
Definition: Ownership.h:264
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition: OpenMPKinds.h:92
@ OMPC_MOTION_MODIFIER_unknown
Definition: OpenMPKinds.h:96
bool operator!=(CanQual< T > x, CanQual< U > y)
@ OMPC_DEFAULTMAP_unknown
Definition: OpenMPKinds.h:115
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
Definition: OpenMPKinds.h:227
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition: OpenMPKinds.h:63
@ OMPC_LINEAR_unknown
Definition: OpenMPKinds.h:67
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
const FunctionProtoType * T
StmtResult StmtEmpty()
Definition: Ownership.h:272
@ OMPC_DEVICE_unknown
Definition: OpenMPKinds.h:51
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition: OpenMPKinds.h:79
@ OMPC_MAP_MODIFIER_unknown
Definition: OpenMPKinds.h:80
@ OMPC_ORDER_unknown
Definition: OpenMPKinds.h:168
@ OMPC_SCHEDULE_unknown
Definition: OpenMPKinds.h:35
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:123
@ AS_none
Definition: Specifiers.h:127
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition: OpenMPKinds.h:71
@ OMPC_MAP_unknown
Definition: OpenMPKinds.h:75
#define false
Definition: stdbool.h:26
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:240
llvm::omp::TraitProperty Kind
StringRef RawString
The raw string as we parsed it.
llvm::omp::TraitSelector Kind
llvm::SmallVector< OMPTraitProperty, 1 > Properties
llvm::omp::TraitSet Kind
llvm::SmallVector< OMPTraitSelector, 2 > Selectors
This structure contains most locations needed for by an OMPVarListClause.
Definition: OpenMPClause.h:259
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition: SemaOpenMP.h:316
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition: SemaOpenMP.h:313
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition: SemaOpenMP.h:310
SourceLocation Loc
The directive location.
Definition: SemaOpenMP.h:319
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition: SemaOpenMP.h:307
Data structure for iterator expression.
Definition: SemaOpenMP.h:1387
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1130
Data for list of allocators.
Definition: SemaOpenMP.h:1327
Clang specific specialization of the OMPContext to lookup target features.