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

source code of clang/lib/Parse/ParseOpenMP.cpp