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

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