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