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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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