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