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