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(DeclForInitializer: OmpPrivParm);
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 RequiresToLinkLocalOrIndirectClause = false;
1762 bool HasToLinkLocalOrIndirectClause = false;
1763 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
1764 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1765 bool HasIdentifier = Tok.is(K: tok::identifier);
1766 if (HasIdentifier) {
1767 // If we see any clause we need a to, link, or local clause.
1768 RequiresToLinkLocalOrIndirectClause = true;
1769 IdentifierInfo *II = Tok.getIdentifierInfo();
1770 StringRef ClauseName = II->getName();
1771 bool IsDeviceTypeClause =
1772 getLangOpts().OpenMP >= 50 &&
1773 getOpenMPClauseKind(Str: ClauseName) == OMPC_device_type;
1774
1775 bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
1776 getOpenMPClauseKind(Str: ClauseName) == OMPC_indirect;
1777
1778 if (DTCI.Indirect && IsIndirectClause) {
1779 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1780 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
1781 << getOpenMPDirectiveName(D: OMPD_declare_target, Ver: OMPVersion)
1782 << getOpenMPClauseName(C: OMPC_indirect) << 0;
1783 break;
1784 }
1785 bool IsToEnterLinkOrLocalClause =
1786 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(Val: ClauseName, Out&: MT);
1787 assert((!IsDeviceTypeClause || !IsToEnterLinkOrLocalClause) &&
1788 "Cannot be both!");
1789
1790 // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1791 // `enter` clause.
1792 if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
1793 Diag(Tok, DiagID: diag::err_omp_declare_target_unexpected_to_clause);
1794 break;
1795 }
1796 if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
1797 Diag(Tok, DiagID: diag::err_omp_declare_target_unexpected_enter_clause);
1798 break;
1799 }
1800
1801 // The 'local' clause is only available in OpenMP 6.0.
1802 if (getLangOpts().OpenMP < 60 && ClauseName == "local") {
1803 Diag(Tok, DiagID: getLangOpts().OpenMP >= 52
1804 ? diag::err_omp_declare_target_unexpected_clause_52
1805 : diag::err_omp_declare_target_unexpected_clause)
1806 << ClauseName
1807 << (getLangOpts().OpenMP >= 51 ? 4
1808 : getLangOpts().OpenMP >= 50 ? 2
1809 : 1);
1810 break;
1811 }
1812
1813 if (!IsDeviceTypeClause && !IsIndirectClause &&
1814 DTCI.Kind == OMPD_begin_declare_target) {
1815 Diag(Tok, DiagID: getLangOpts().OpenMP >= 52
1816 ? diag::err_omp_declare_target_unexpected_clause_52
1817 : diag::err_omp_declare_target_unexpected_clause)
1818 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
1819 break;
1820 }
1821
1822 if (!IsDeviceTypeClause && !IsToEnterLinkOrLocalClause &&
1823 !IsIndirectClause) {
1824 Diag(Tok, DiagID: getLangOpts().OpenMP >= 52
1825 ? diag::err_omp_declare_target_unexpected_clause_52
1826 : diag::err_omp_declare_target_unexpected_clause)
1827 << ClauseName
1828 << (getLangOpts().OpenMP > 52 ? 5
1829 : getLangOpts().OpenMP >= 51 ? 4
1830 : getLangOpts().OpenMP >= 50 ? 2
1831 : 1);
1832 break;
1833 }
1834
1835 if (IsToEnterLinkOrLocalClause || IsIndirectClause)
1836 HasToLinkLocalOrIndirectClause = true;
1837
1838 if (IsIndirectClause) {
1839 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
1840 break;
1841 continue;
1842 }
1843 // Parse 'device_type' clause and go to next clause if any.
1844 if (IsDeviceTypeClause) {
1845 std::optional<SimpleClauseData> DevTypeData =
1846 parseOpenMPSimpleClause(P&: *this, Kind: OMPC_device_type);
1847 if (DevTypeData) {
1848 if (DeviceTypeLoc.isValid()) {
1849 // We already saw another device_type clause, diagnose it.
1850 Diag(Loc: DevTypeData->Loc,
1851 DiagID: diag::warn_omp_more_one_device_type_clause);
1852 break;
1853 }
1854 switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
1855 case OMPC_DEVICE_TYPE_any:
1856 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1857 break;
1858 case OMPC_DEVICE_TYPE_host:
1859 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1860 break;
1861 case OMPC_DEVICE_TYPE_nohost:
1862 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1863 break;
1864 case OMPC_DEVICE_TYPE_unknown:
1865 llvm_unreachable("Unexpected device_type");
1866 }
1867 DeviceTypeLoc = DevTypeData->Loc;
1868 }
1869 continue;
1870 }
1871 ConsumeToken();
1872 }
1873
1874 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1875 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1876 DeclarationNameInfo NameInfo) {
1877 NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
1878 CurScope: getCurScope(), ScopeSpec&: SS, Id: NameInfo);
1879 if (!ND)
1880 return;
1881 SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{.MT: MT, .Loc: NameInfo.getLoc()};
1882 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(Key: ND, Args&: MI).second;
1883 if (!FirstMapping)
1884 Diag(Loc: NameInfo.getLoc(), DiagID: diag::err_omp_declare_target_multiple)
1885 << NameInfo.getName();
1886 };
1887 if (ParseOpenMPSimpleVarList(Kind: OMPD_declare_target, Callback,
1888 /*AllowScopeSpecifier=*/true))
1889 break;
1890 }
1891
1892 if (Tok.is(K: tok::l_paren)) {
1893 Diag(Tok,
1894 DiagID: diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1895 break;
1896 }
1897 if (!HasIdentifier && Tok.isNot(K: tok::annot_pragma_openmp_end)) {
1898 Diag(Tok,
1899 DiagID: getLangOpts().OpenMP >= 52
1900 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1901 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1902 break;
1903 }
1904
1905 // Consume optional ','.
1906 if (Tok.is(K: tok::comma))
1907 ConsumeToken();
1908 }
1909
1910 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1911 Diag(Loc: DeviceTypeLoc, DiagID: diag::err_omp_declare_target_indirect_device_type);
1912
1913 // declare target requires at least one clause.
1914 if (DTCI.Kind == OMPD_declare_target && RequiresToLinkLocalOrIndirectClause &&
1915 !HasToLinkLocalOrIndirectClause)
1916 Diag(Loc: DTCI.Loc, DiagID: diag::err_omp_declare_target_missing_required_clause)
1917 << (getLangOpts().OpenMP >= 60 ? 3
1918 : getLangOpts().OpenMP == 52 ? 2
1919 : getLangOpts().OpenMP == 51 ? 1
1920 : 0);
1921
1922 SkipUntil(T: tok::annot_pragma_openmp_end, Flags: StopBeforeMatch);
1923}
1924
1925void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1926 // The last seen token is annot_pragma_openmp_end - need to check for
1927 // extra tokens.
1928 if (Tok.is(K: tok::annot_pragma_openmp_end))
1929 return;
1930
1931 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1932 Diag(Tok, DiagID: diag::warn_omp_extra_tokens_at_eol)
1933 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
1934 while (Tok.isNot(K: tok::annot_pragma_openmp_end))
1935 ConsumeAnyToken();
1936}
1937
1938void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1939 OpenMPDirectiveKind ExpectedKind,
1940 OpenMPDirectiveKind FoundKind,
1941 SourceLocation BeginLoc,
1942 SourceLocation FoundLoc,
1943 bool SkipUntilOpenMPEnd) {
1944 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1945
1946 if (FoundKind == ExpectedKind) {
1947 ConsumeAnyToken();
1948 skipUntilPragmaOpenMPEnd(DKind: ExpectedKind);
1949 return;
1950 }
1951
1952 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1953 Diag(Loc: FoundLoc, DiagID: diag::err_expected_end_declare_target_or_variant)
1954 << DiagSelection;
1955 Diag(Loc: BeginLoc, DiagID: diag::note_matching)
1956 << ("'#pragma omp " + getOpenMPDirectiveName(D: BeginKind, Ver: OMPVersion) + "'")
1957 .str();
1958 if (SkipUntilOpenMPEnd)
1959 SkipUntil(T: tok::annot_pragma_openmp_end, Flags: StopBeforeMatch);
1960}
1961
1962void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
1963 OpenMPDirectiveKind EndDKind,
1964 SourceLocation DKLoc) {
1965 parseOMPEndDirective(BeginKind: BeginDKind, ExpectedKind: OMPD_end_declare_target, FoundKind: EndDKind, BeginLoc: DKLoc,
1966 FoundLoc: Tok.getLocation(),
1967 /* SkipUntilOpenMPEnd */ false);
1968 // Skip the last annot_pragma_openmp_end.
1969 if (Tok.is(K: tok::annot_pragma_openmp_end))
1970 ConsumeAnnotationToken();
1971}
1972
1973Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1974 AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
1975 DeclSpec::TST TagType, Decl *Tag) {
1976 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
1977 "Not an OpenMP directive!");
1978 ParsingOpenMPDirectiveRAII DirScope(*this);
1979 ParenBraceBracketBalancer BalancerRAIIObj(*this);
1980 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
1981
1982 SourceLocation Loc;
1983 OpenMPDirectiveKind DKind;
1984 if (Delayed) {
1985 TentativeParsingAction TPA(*this);
1986 Loc = ConsumeAnnotationToken();
1987 DKind = parseOpenMPDirectiveKind(P&: *this);
1988 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1989 // Need to delay parsing until completion of the parent class.
1990 TPA.Revert();
1991 CachedTokens Toks;
1992 unsigned Cnt = 1;
1993 Toks.push_back(Elt: Tok);
1994 while (Cnt && Tok.isNot(K: tok::eof)) {
1995 (void)ConsumeAnyToken();
1996 if (Tok.isOneOf(Ks: tok::annot_pragma_openmp, Ks: tok::annot_attr_openmp))
1997 ++Cnt;
1998 else if (Tok.is(K: tok::annot_pragma_openmp_end))
1999 --Cnt;
2000 Toks.push_back(Elt: Tok);
2001 }
2002 // Skip last annot_pragma_openmp_end.
2003 if (Cnt == 0)
2004 (void)ConsumeAnyToken();
2005 auto *LP = new LateParsedPragma(this, AS);
2006 LP->takeToks(Cached&: Toks);
2007 getCurrentClass().LateParsedDeclarations.push_back(Elt: LP);
2008 return nullptr;
2009 }
2010 TPA.Commit();
2011 } else {
2012 Loc = ConsumeAnnotationToken();
2013 DKind = parseOpenMPDirectiveKind(P&: *this);
2014 }
2015
2016 switch (DKind) {
2017 case OMPD_threadprivate: {
2018 ConsumeToken();
2019 DeclDirectiveListParserHelper Helper(this, DKind);
2020 if (!ParseOpenMPSimpleVarList(Kind: DKind, Callback: Helper,
2021 /*AllowScopeSpecifier=*/true)) {
2022 skipUntilPragmaOpenMPEnd(DKind);
2023 // Skip the last annot_pragma_openmp_end.
2024 ConsumeAnnotationToken();
2025 return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2026 Loc, VarList: Helper.getIdentifiers());
2027 }
2028 break;
2029 }
2030 case OMPD_groupprivate: {
2031 ConsumeToken();
2032 DeclDirectiveListParserHelper Helper(this, DKind);
2033 if (!ParseOpenMPSimpleVarList(Kind: DKind, Callback: Helper,
2034 /*AllowScopeSpecifier=*/true)) {
2035 skipUntilPragmaOpenMPEnd(DKind);
2036 // Skip the last annot_pragma_openmp_end.
2037 ConsumeAnnotationToken();
2038 return Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2039 Loc, VarList: Helper.getIdentifiers());
2040 }
2041 break;
2042 }
2043 case OMPD_allocate: {
2044 ConsumeToken();
2045 DeclDirectiveListParserHelper Helper(this, DKind);
2046 if (!ParseOpenMPSimpleVarList(Kind: DKind, Callback: Helper,
2047 /*AllowScopeSpecifier=*/true)) {
2048 SmallVector<OMPClause *, 1> Clauses;
2049 if (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2050 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
2051 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2052 OpenMPClauseKind CKind =
2053 Tok.isAnnotation() ? OMPC_unknown
2054 : getOpenMPClauseKind(Str: PP.getSpelling(Tok));
2055 Actions.OpenMP().StartOpenMPClause(K: CKind);
2056 OMPClause *Clause = ParseOpenMPClause(DKind: OMPD_allocate, CKind,
2057 FirstClause: !SeenClauses[unsigned(CKind)]);
2058 SkipUntil(T1: tok::comma, T2: tok::identifier, T3: tok::annot_pragma_openmp_end,
2059 Flags: StopBeforeMatch);
2060 SeenClauses[unsigned(CKind)] = true;
2061 if (Clause != nullptr)
2062 Clauses.push_back(Elt: Clause);
2063 if (Tok.is(K: tok::annot_pragma_openmp_end)) {
2064 Actions.OpenMP().EndOpenMPClause();
2065 break;
2066 }
2067 // Skip ',' if any.
2068 if (Tok.is(K: tok::comma))
2069 ConsumeToken();
2070 Actions.OpenMP().EndOpenMPClause();
2071 }
2072 skipUntilPragmaOpenMPEnd(DKind);
2073 }
2074 // Skip the last annot_pragma_openmp_end.
2075 ConsumeAnnotationToken();
2076 return Actions.OpenMP().ActOnOpenMPAllocateDirective(
2077 Loc, VarList: Helper.getIdentifiers(), Clauses);
2078 }
2079 break;
2080 }
2081 case OMPD_requires: {
2082 SourceLocation StartLoc = ConsumeToken();
2083 SmallVector<OMPClause *, 5> Clauses;
2084 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2085 if (Tok.is(K: tok::annot_pragma_openmp_end)) {
2086 Diag(Tok, DiagID: diag::err_omp_expected_clause)
2087 << getOpenMPDirectiveName(D: OMPD_requires, Ver: OMPVersion);
2088 break;
2089 }
2090 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2091 OpenMPClauseKind CKind = Tok.isAnnotation()
2092 ? OMPC_unknown
2093 : getOpenMPClauseKind(Str: PP.getSpelling(Tok));
2094 Actions.OpenMP().StartOpenMPClause(K: CKind);
2095 OMPClause *Clause = ParseOpenMPClause(DKind: OMPD_requires, CKind,
2096 FirstClause: !SeenClauses[unsigned(CKind)]);
2097 SkipUntil(T1: tok::comma, T2: tok::identifier, T3: tok::annot_pragma_openmp_end,
2098 Flags: StopBeforeMatch);
2099 SeenClauses[unsigned(CKind)] = true;
2100 if (Clause != nullptr)
2101 Clauses.push_back(Elt: Clause);
2102 if (Tok.is(K: tok::annot_pragma_openmp_end)) {
2103 Actions.OpenMP().EndOpenMPClause();
2104 break;
2105 }
2106 // Skip ',' if any.
2107 if (Tok.is(K: tok::comma))
2108 ConsumeToken();
2109 Actions.OpenMP().EndOpenMPClause();
2110 }
2111 // Consume final annot_pragma_openmp_end
2112 if (Clauses.empty()) {
2113 Diag(Tok, DiagID: diag::err_omp_expected_clause)
2114 << getOpenMPDirectiveName(D: OMPD_requires, Ver: OMPVersion);
2115 ConsumeAnnotationToken();
2116 return nullptr;
2117 }
2118 ConsumeAnnotationToken();
2119 return Actions.OpenMP().ActOnOpenMPRequiresDirective(Loc: StartLoc, ClauseList: Clauses);
2120 }
2121 case OMPD_error: {
2122 SmallVector<OMPClause *, 1> Clauses;
2123 SourceLocation StartLoc = ConsumeToken();
2124 ParseOpenMPClauses(DKind, Clauses, Loc: StartLoc);
2125 Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
2126 EndLoc: SourceLocation(),
2127 /*InExContext = */ false);
2128 break;
2129 }
2130 case OMPD_assumes:
2131 case OMPD_begin_assumes:
2132 ParseOpenMPAssumesDirective(DKind, Loc: ConsumeToken());
2133 break;
2134 case OMPD_end_assumes:
2135 ParseOpenMPEndAssumesDirective(Loc: ConsumeToken());
2136 break;
2137 case OMPD_declare_reduction:
2138 ConsumeToken();
2139 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2140 skipUntilPragmaOpenMPEnd(DKind: OMPD_declare_reduction);
2141 // Skip the last annot_pragma_openmp_end.
2142 ConsumeAnnotationToken();
2143 return Res;
2144 }
2145 break;
2146 case OMPD_declare_mapper: {
2147 ConsumeToken();
2148 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2149 // Skip the last annot_pragma_openmp_end.
2150 ConsumeAnnotationToken();
2151 return Res;
2152 }
2153 break;
2154 }
2155 case OMPD_begin_declare_variant: {
2156 ConsumeToken();
2157 if (!ParseOpenMPDeclareBeginVariantDirective(Loc)) {
2158 // Skip the last annot_pragma_openmp_end.
2159 if (!isEofOrEom())
2160 ConsumeAnnotationToken();
2161 }
2162 return nullptr;
2163 }
2164 case OMPD_end_declare_variant: {
2165 ConsumeToken();
2166 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2167 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2168 else
2169 Diag(Loc, DiagID: diag::err_expected_begin_declare_variant);
2170 // Skip the last annot_pragma_openmp_end.
2171 ConsumeAnnotationToken();
2172 return nullptr;
2173 }
2174 case OMPD_declare_variant:
2175 case OMPD_declare_simd: {
2176 // The syntax is:
2177 // { #pragma omp declare {simd|variant} }
2178 // <function-declaration-or-definition>
2179 //
2180 CachedTokens Toks;
2181 Toks.push_back(Elt: Tok);
2182 ConsumeToken();
2183 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2184 Toks.push_back(Elt: Tok);
2185 ConsumeAnyToken();
2186 }
2187 Toks.push_back(Elt: Tok);
2188 ConsumeAnyToken();
2189
2190 DeclGroupPtrTy Ptr;
2191 if (Tok.isOneOf(Ks: tok::annot_pragma_openmp, Ks: tok::annot_attr_openmp)) {
2192 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2193 TagType, Tag);
2194 } else if (Tok.isNot(K: tok::r_brace) && !isEofOrEom()) {
2195 // Here we expect to see some function declaration.
2196 if (AS == AS_none) {
2197 assert(TagType == DeclSpec::TST_unspecified);
2198 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2199 MaybeParseCXX11Attributes(Attrs);
2200 ParsingDeclSpec PDS(*this);
2201 Ptr = ParseExternalDeclaration(DeclAttrs&: Attrs, DeclSpecAttrs&: EmptyDeclSpecAttrs, DS: &PDS);
2202 } else {
2203 Ptr =
2204 ParseCXXClassMemberDeclarationWithPragmas(AS, AccessAttrs&: Attrs, TagType, Tag);
2205 }
2206 }
2207 if (!Ptr) {
2208 Diag(Loc, DiagID: diag::err_omp_decl_in_declare_simd_variant)
2209 << (DKind == OMPD_declare_simd ? 0 : 1);
2210 return DeclGroupPtrTy();
2211 }
2212 if (DKind == OMPD_declare_simd)
2213 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2214 assert(DKind == OMPD_declare_variant &&
2215 "Expected declare variant directive only");
2216 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2217 return Ptr;
2218 }
2219 case OMPD_begin_declare_target:
2220 case OMPD_declare_target: {
2221 SourceLocation DTLoc = ConsumeAnyToken();
2222 bool HasClauses = Tok.isNot(K: tok::annot_pragma_openmp_end);
2223 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2224 if (DKind == OMPD_declare_target && !HasClauses &&
2225 getLangOpts().OpenMP >= 52)
2226 Diag(Loc: DTLoc, DiagID: diag::warn_omp_deprecated_declare_target_delimited_form);
2227 if (HasClauses)
2228 ParseOMPDeclareTargetClauses(DTCI);
2229 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2230 !HasClauses ||
2231 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2232
2233 // Skip the last annot_pragma_openmp_end.
2234 ConsumeAnyToken();
2235
2236 if (HasImplicitMappings) {
2237 Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
2238 return nullptr;
2239 }
2240
2241 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2242 llvm::SmallVector<Decl *, 4> Decls;
2243 for (auto &It : DTCI.ExplicitlyMapped)
2244 Decls.push_back(Elt: It.first);
2245 return Actions.BuildDeclaratorGroup(Group: Decls);
2246 }
2247 case OMPD_end_declare_target: {
2248 if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
2249 Diag(Tok, DiagID: diag::err_omp_unexpected_directive)
2250 << 1 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
2251 break;
2252 }
2253 const SemaOpenMP::DeclareTargetContextInfo &DTCI =
2254 Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
2255 ParseOMPEndDeclareTargetDirective(BeginDKind: DTCI.Kind, EndDKind: DKind, DKLoc: DTCI.Loc);
2256 return nullptr;
2257 }
2258 case OMPD_assume: {
2259 Diag(Tok, DiagID: diag::err_omp_unexpected_directive)
2260 << 1 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
2261 break;
2262 }
2263 case OMPD_unknown:
2264 Diag(Tok, DiagID: diag::err_omp_unknown_directive);
2265 break;
2266 default:
2267 switch (getDirectiveCategory(D: DKind)) {
2268 case Category::Executable:
2269 case Category::Meta:
2270 case Category::Subsidiary:
2271 case Category::Utility:
2272 Diag(Tok, DiagID: diag::err_omp_unexpected_directive)
2273 << 1 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
2274 break;
2275 case Category::Declarative:
2276 case Category::Informational:
2277 break;
2278 }
2279 }
2280 while (Tok.isNot(K: tok::annot_pragma_openmp_end))
2281 ConsumeAnyToken();
2282 ConsumeAnyToken();
2283 return nullptr;
2284}
2285
2286StmtResult Parser::ParseOpenMPExecutableDirective(
2287 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2288 bool ReadDirectiveWithinMetadirective) {
2289 assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2290 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2291
2292 bool HasAssociatedStatement = true;
2293 Association Assoc = getDirectiveAssociation(D: DKind);
2294
2295 // OMPD_ordered has None as association, but it comes in two variants,
2296 // the second of which is associated with a block.
2297 // OMPD_scan and OMPD_section are both "separating", but section is treated
2298 // as if it was associated with a statement, while scan is not.
2299 if (DKind != OMPD_ordered && DKind != OMPD_section &&
2300 (Assoc == Association::None || Assoc == Association::Separating)) {
2301 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2302 ParsedStmtContext()) {
2303 Diag(Tok, DiagID: diag::err_omp_immediate_directive)
2304 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << 0;
2305 if (DKind == OMPD_error) {
2306 SkipUntil(T: tok::annot_pragma_openmp_end);
2307 return StmtError();
2308 }
2309 }
2310 HasAssociatedStatement = false;
2311 }
2312
2313 SourceLocation EndLoc;
2314 SmallVector<OMPClause *, 5> Clauses;
2315 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2316 DeclarationNameInfo DirName;
2317 OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2318 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2319 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
2320
2321 // Special processing for flush and depobj clauses.
2322 Token ImplicitTok;
2323 bool ImplicitClauseAllowed = false;
2324 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2325 ImplicitTok = Tok;
2326 ImplicitClauseAllowed = true;
2327 }
2328 ConsumeToken();
2329 // Parse directive name of the 'critical' directive if any.
2330 if (DKind == OMPD_critical) {
2331 BalancedDelimiterTracker T(*this, tok::l_paren,
2332 tok::annot_pragma_openmp_end);
2333 if (!T.consumeOpen()) {
2334 if (Tok.isAnyIdentifier()) {
2335 DirName =
2336 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2337 ConsumeAnyToken();
2338 } else {
2339 Diag(Tok, DiagID: diag::err_omp_expected_identifier_for_critical);
2340 }
2341 T.consumeClose();
2342 }
2343 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2344 CancelRegion = parseOpenMPDirectiveKind(P&: *this);
2345 if (Tok.isNot(K: tok::annot_pragma_openmp_end))
2346 ConsumeAnyToken();
2347 }
2348
2349 if (isOpenMPLoopDirective(DKind))
2350 ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2351 if (isOpenMPSimdDirective(DKind))
2352 ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2353 ParseScope OMPDirectiveScope(this, ScopeFlags);
2354 Actions.OpenMP().StartOpenMPDSABlock(K: DKind, DirName, CurScope: Actions.getCurScope(),
2355 Loc);
2356
2357 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2358 // If we are parsing for a directive within a metadirective, the directive
2359 // ends with a ')'.
2360 if (ReadDirectiveWithinMetadirective && Tok.is(K: tok::r_paren)) {
2361 while (Tok.isNot(K: tok::annot_pragma_openmp_end))
2362 ConsumeAnyToken();
2363 break;
2364 }
2365 bool HasImplicitClause = false;
2366 if (ImplicitClauseAllowed && Tok.is(K: tok::l_paren)) {
2367 HasImplicitClause = true;
2368 // Push copy of the current token back to stream to properly parse
2369 // pseudo-clause OMPFlushClause or OMPDepobjClause.
2370 PP.EnterToken(Tok, /*IsReinject*/ true);
2371 PP.EnterToken(Tok: ImplicitTok, /*IsReinject*/ true);
2372 ConsumeAnyToken();
2373 }
2374 OpenMPClauseKind CKind = Tok.isAnnotation()
2375 ? OMPC_unknown
2376 : getOpenMPClauseKind(Str: PP.getSpelling(Tok));
2377 if (HasImplicitClause) {
2378 assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2379 if (DKind == OMPD_flush) {
2380 CKind = OMPC_flush;
2381 } else {
2382 assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2383 CKind = OMPC_depobj;
2384 }
2385 }
2386 // No more implicit clauses allowed.
2387 ImplicitClauseAllowed = false;
2388 Actions.OpenMP().StartOpenMPClause(K: CKind);
2389 HasImplicitClause = false;
2390 OMPClause *Clause =
2391 ParseOpenMPClause(DKind, CKind, FirstClause: !SeenClauses[unsigned(CKind)]);
2392 SeenClauses[unsigned(CKind)] = true;
2393 if (Clause)
2394 Clauses.push_back(Elt: Clause);
2395
2396 // Skip ',' if any.
2397 if (Tok.is(K: tok::comma))
2398 ConsumeToken();
2399 Actions.OpenMP().EndOpenMPClause();
2400 }
2401 // End location of the directive.
2402 EndLoc = Tok.getLocation();
2403 // Consume final annot_pragma_openmp_end.
2404 ConsumeAnnotationToken();
2405
2406 if (DKind == OMPD_ordered) {
2407 // If the depend or doacross clause is specified, the ordered construct
2408 // is a stand-alone directive.
2409 for (auto CK : {OMPC_depend, OMPC_doacross}) {
2410 if (SeenClauses[unsigned(CK)]) {
2411 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2412 ParsedStmtContext()) {
2413 Diag(Loc, DiagID: diag::err_omp_immediate_directive)
2414 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << 1
2415 << getOpenMPClauseName(C: CK);
2416 }
2417 HasAssociatedStatement = false;
2418 }
2419 }
2420 }
2421
2422 if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
2423 !SeenClauses[unsigned(OMPC_sizes)]) {
2424 Diag(Loc, DiagID: diag::err_omp_required_clause)
2425 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << "sizes";
2426 }
2427
2428 StmtResult AssociatedStmt;
2429 if (HasAssociatedStatement) {
2430 // The body is a block scope like in Lambdas and Blocks.
2431 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, CurScope: getCurScope());
2432 // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2433 // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2434 // should have at least one compound statement scope within it.
2435 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2436 {
2437 Sema::CompoundScopeRAII Scope(Actions);
2438 AssociatedStmt = ParseStatement();
2439
2440 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2441 getLangOpts().OpenMPIRBuilder)
2442 AssociatedStmt =
2443 Actions.OpenMP().ActOnOpenMPLoopnest(AStmt: AssociatedStmt.get());
2444 }
2445 AssociatedStmt =
2446 Actions.OpenMP().ActOnOpenMPRegionEnd(S: AssociatedStmt, Clauses);
2447 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2448 DKind == OMPD_target_exit_data) {
2449 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, CurScope: getCurScope());
2450 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2451 Actions.ActOnCompoundStmt(L: Loc, R: Loc, Elts: {},
2452 /*isStmtExpr=*/false));
2453 AssociatedStmt =
2454 Actions.OpenMP().ActOnOpenMPRegionEnd(S: AssociatedStmt, Clauses);
2455 }
2456
2457 StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
2458 Kind: DKind, DirName, CancelRegion, Clauses, AStmt: AssociatedStmt.get(), StartLoc: Loc, EndLoc);
2459
2460 // Exit scope.
2461 Actions.OpenMP().EndOpenMPDSABlock(CurDirective: Directive.get());
2462 OMPDirectiveScope.Exit();
2463
2464 return Directive;
2465}
2466
2467StmtResult Parser::ParseOpenMPInformationalDirective(
2468 ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2469 bool ReadDirectiveWithinMetadirective) {
2470 assert(isOpenMPInformationalDirective(DKind) &&
2471 "Unexpected directive category");
2472
2473 bool HasAssociatedStatement = true;
2474
2475 SmallVector<OMPClause *, 5> Clauses;
2476 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2477 DeclarationNameInfo DirName;
2478 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2479 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
2480 ParseScope OMPDirectiveScope(this, ScopeFlags);
2481
2482 Actions.OpenMP().StartOpenMPDSABlock(K: DKind, DirName, CurScope: Actions.getCurScope(),
2483 Loc);
2484
2485 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2486 if (ReadDirectiveWithinMetadirective && Tok.is(K: tok::r_paren)) {
2487 while (Tok.isNot(K: tok::annot_pragma_openmp_end))
2488 ConsumeAnyToken();
2489 break;
2490 }
2491
2492 OpenMPClauseKind CKind = Tok.isAnnotation()
2493 ? OMPC_unknown
2494 : getOpenMPClauseKind(Str: PP.getSpelling(Tok));
2495 Actions.OpenMP().StartOpenMPClause(K: CKind);
2496 OMPClause *Clause =
2497 ParseOpenMPClause(DKind, CKind, FirstClause: !SeenClauses[unsigned(CKind)]);
2498 SeenClauses[unsigned(CKind)] = true;
2499 if (Clause)
2500 Clauses.push_back(Elt: Clause);
2501
2502 if (Tok.is(K: tok::comma))
2503 ConsumeToken();
2504 Actions.OpenMP().EndOpenMPClause();
2505 }
2506
2507 SourceLocation EndLoc = Tok.getLocation();
2508 ConsumeAnnotationToken();
2509
2510 StmtResult AssociatedStmt;
2511 if (HasAssociatedStatement) {
2512 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, CurScope: getCurScope());
2513 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2514 {
2515 Sema::CompoundScopeRAII Scope(Actions);
2516 AssociatedStmt = ParseStatement();
2517 }
2518 AssociatedStmt =
2519 Actions.OpenMP().ActOnOpenMPRegionEnd(S: AssociatedStmt, Clauses);
2520 }
2521
2522 StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(
2523 Kind: DKind, DirName, Clauses, AStmt: AssociatedStmt.get(), StartLoc: Loc, EndLoc);
2524
2525 Actions.OpenMP().EndOpenMPDSABlock(CurDirective: Directive.get());
2526 OMPDirectiveScope.Exit();
2527
2528 return Directive;
2529}
2530
2531StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2532 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2533 if (!ReadDirectiveWithinMetadirective)
2534 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2535 "Not an OpenMP directive!");
2536 ParsingOpenMPDirectiveRAII DirScope(*this);
2537 ParenBraceBracketBalancer BalancerRAIIObj(*this);
2538 SourceLocation Loc = ReadDirectiveWithinMetadirective
2539 ? Tok.getLocation()
2540 : ConsumeAnnotationToken();
2541 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2542 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(P&: *this);
2543 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2544 Diag(Tok, DiagID: diag::err_omp_unknown_directive);
2545 return StmtError();
2546 }
2547
2548 StmtResult Directive = StmtError();
2549
2550 bool IsExecutable = [&]() {
2551 if (DKind == OMPD_error) // OMPD_error is handled as executable
2552 return true;
2553 auto Res = getDirectiveCategory(D: DKind);
2554 return Res == Category::Executable || Res == Category::Subsidiary;
2555 }();
2556
2557 if (IsExecutable) {
2558 Directive = ParseOpenMPExecutableDirective(
2559 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2560 assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2561 return Directive;
2562 }
2563
2564 switch (DKind) {
2565 case OMPD_nothing:
2566 ConsumeToken();
2567 // If we are parsing the directive within a metadirective, the directive
2568 // ends with a ')'.
2569 if (ReadDirectiveWithinMetadirective && Tok.is(K: tok::r_paren))
2570 while (Tok.isNot(K: tok::annot_pragma_openmp_end))
2571 ConsumeAnyToken();
2572 else
2573 skipUntilPragmaOpenMPEnd(DKind);
2574 if (Tok.is(K: tok::annot_pragma_openmp_end))
2575 ConsumeAnnotationToken();
2576 // return an empty statement
2577 return StmtEmpty();
2578 case OMPD_metadirective: {
2579 ConsumeToken();
2580 SmallVector<VariantMatchInfo, 4> VMIs;
2581
2582 // First iteration of parsing all clauses of metadirective.
2583 // This iteration only parses and collects all context selector ignoring the
2584 // associated directives.
2585 TentativeParsingAction TPA(*this);
2586 ASTContext &ASTContext = Actions.getASTContext();
2587
2588 BalancedDelimiterTracker T(*this, tok::l_paren,
2589 tok::annot_pragma_openmp_end);
2590 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2591 OpenMPClauseKind CKind = Tok.isAnnotation()
2592 ? OMPC_unknown
2593 : getOpenMPClauseKind(Str: PP.getSpelling(Tok));
2594 // Check if the clause is unrecognized.
2595 if (CKind == OMPC_unknown) {
2596 Diag(Tok, DiagID: diag::err_omp_expected_clause) << "metadirective";
2597 TPA.Revert();
2598 SkipUntil(T: tok::annot_pragma_openmp_end);
2599 return Directive;
2600 }
2601 if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise)
2602 Diag(Tok, DiagID: diag::err_omp_unexpected_clause)
2603 << getOpenMPClauseName(C: CKind) << "metadirective";
2604 if (CKind == OMPC_default && getLangOpts().OpenMP >= 52)
2605 Diag(Tok, DiagID: diag::warn_omp_default_deprecated);
2606
2607 SourceLocation Loc = ConsumeToken();
2608
2609 // Parse '('.
2610 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after,
2611 Msg: getOpenMPClauseName(C: CKind).data())) {
2612 TPA.Revert();
2613 SkipUntil(T: tok::annot_pragma_openmp_end);
2614 return Directive;
2615 }
2616
2617 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2618 if (CKind == OMPC_when) {
2619 // parse and get OMPTraitInfo to pass to the When clause
2620 parseOMPContextSelectors(Loc, TI);
2621 if (TI.Sets.size() == 0) {
2622 Diag(Tok, DiagID: diag::err_omp_expected_context_selector) << "when clause";
2623 TPA.Commit();
2624 return Directive;
2625 }
2626
2627 // Parse ':'
2628 if (Tok.is(K: tok::colon))
2629 ConsumeAnyToken();
2630 else {
2631 Diag(Tok, DiagID: diag::err_omp_expected_colon) << "when clause";
2632 TPA.Commit();
2633 return Directive;
2634 }
2635 }
2636
2637 // Skip Directive for now. We will parse directive in the second iteration
2638 int paren = 0;
2639 while (Tok.isNot(K: tok::r_paren) || paren != 0) {
2640 if (Tok.is(K: tok::l_paren))
2641 paren++;
2642 if (Tok.is(K: tok::r_paren))
2643 paren--;
2644 if (Tok.is(K: tok::annot_pragma_openmp_end)) {
2645 Diag(Tok, DiagID: diag::err_omp_expected_punc)
2646 << getOpenMPClauseName(C: CKind) << 0;
2647 TPA.Commit();
2648 return Directive;
2649 }
2650 ConsumeAnyToken();
2651 }
2652 // Parse ')'
2653 if (Tok.is(K: tok::r_paren))
2654 T.consumeClose();
2655
2656 VariantMatchInfo VMI;
2657 TI.getAsVariantMatchInfo(ASTCtx&: ASTContext, VMI);
2658
2659 VMIs.push_back(Elt: VMI);
2660 }
2661
2662 TPA.Revert();
2663 // End of the first iteration. Parser is reset to the start of metadirective
2664
2665 std::function<void(StringRef)> DiagUnknownTrait =
2666 [this, Loc](StringRef ISATrait) {
2667 // TODO Track the selector locations in a way that is accessible here
2668 // to improve the diagnostic location.
2669 Diag(Loc, DiagID: diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2670 };
2671 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2672 /* CurrentFunctionDecl */ nullptr,
2673 ArrayRef<llvm::omp::TraitProperty>(),
2674 Actions.OpenMP().getOpenMPDeviceNum());
2675
2676 // A single match is returned for OpenMP 5.0
2677 int BestIdx = getBestVariantMatchForContext(VMIs, Ctx: OMPCtx);
2678
2679 int Idx = 0;
2680 // In OpenMP 5.0 metadirective is either replaced by another directive or
2681 // ignored.
2682 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2683 // found by getBestWhenMatchForContext.
2684 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2685 // OpenMP 5.0 implementation - Skip to the best index found.
2686 if (Idx++ != BestIdx) {
2687 ConsumeToken(); // Consume clause name
2688 T.consumeOpen(); // Consume '('
2689 int paren = 0;
2690 // Skip everything inside the clause
2691 while (Tok.isNot(K: tok::r_paren) || paren != 0) {
2692 if (Tok.is(K: tok::l_paren))
2693 paren++;
2694 if (Tok.is(K: tok::r_paren))
2695 paren--;
2696 ConsumeAnyToken();
2697 }
2698 // Parse ')'
2699 if (Tok.is(K: tok::r_paren))
2700 T.consumeClose();
2701 continue;
2702 }
2703
2704 OpenMPClauseKind CKind = Tok.isAnnotation()
2705 ? OMPC_unknown
2706 : getOpenMPClauseKind(Str: PP.getSpelling(Tok));
2707 SourceLocation Loc = ConsumeToken();
2708
2709 // Parse '('.
2710 T.consumeOpen();
2711
2712 // Skip ContextSelectors for when clause
2713 if (CKind == OMPC_when) {
2714 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2715 // parse and skip the ContextSelectors
2716 parseOMPContextSelectors(Loc, TI);
2717
2718 // Parse ':'
2719 ConsumeAnyToken();
2720 }
2721
2722 // If no directive is passed, skip in OpenMP 5.0.
2723 // TODO: Generate nothing directive from OpenMP 5.1.
2724 if (Tok.is(K: tok::r_paren)) {
2725 SkipUntil(T: tok::annot_pragma_openmp_end);
2726 break;
2727 }
2728
2729 // Parse Directive
2730 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2731 StmtCtx,
2732 /*ReadDirectiveWithinMetadirective=*/true);
2733 break;
2734 }
2735 // If no match is found and no otherwise clause is present, skip
2736 // OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as
2737 // if one was specified without an associated directive variant.
2738 if (BestIdx == -1 && Idx > 0) {
2739 assert(Tok.is(tok::annot_pragma_openmp_end) &&
2740 "Expecting the end of the pragma here");
2741 ConsumeAnnotationToken();
2742 return StmtEmpty();
2743 }
2744 break;
2745 }
2746 case OMPD_threadprivate: {
2747 // FIXME: Should this be permitted in C++?
2748 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2749 ParsedStmtContext()) {
2750 Diag(Tok, DiagID: diag::err_omp_immediate_directive)
2751 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << 0;
2752 }
2753 ConsumeToken();
2754 DeclDirectiveListParserHelper Helper(this, DKind);
2755 if (!ParseOpenMPSimpleVarList(Kind: DKind, Callback: Helper,
2756 /*AllowScopeSpecifier=*/false)) {
2757 skipUntilPragmaOpenMPEnd(DKind);
2758 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2759 Loc, VarList: Helper.getIdentifiers());
2760 Directive = Actions.ActOnDeclStmt(Decl: Res, StartLoc: Loc, EndLoc: Tok.getLocation());
2761 }
2762 SkipUntil(T: tok::annot_pragma_openmp_end);
2763 break;
2764 }
2765 case OMPD_groupprivate: {
2766 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2767 ParsedStmtContext()) {
2768 Diag(Tok, DiagID: diag::err_omp_immediate_directive)
2769 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << 0;
2770 }
2771 ConsumeToken();
2772 DeclDirectiveListParserHelper Helper(this, DKind);
2773 if (!ParseOpenMPSimpleVarList(Kind: DKind, Callback: Helper,
2774 /*AllowScopeSpecifier=*/false)) {
2775 skipUntilPragmaOpenMPEnd(DKind);
2776 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(
2777 Loc, VarList: Helper.getIdentifiers());
2778 Directive = Actions.ActOnDeclStmt(Decl: Res, StartLoc: Loc, EndLoc: Tok.getLocation());
2779 }
2780 SkipUntil(T: tok::annot_pragma_openmp_end);
2781 break;
2782 }
2783 case OMPD_allocate: {
2784 // FIXME: Should this be permitted in C++?
2785 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2786 ParsedStmtContext()) {
2787 Diag(Tok, DiagID: diag::err_omp_immediate_directive)
2788 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion) << 0;
2789 }
2790 ConsumeToken();
2791 DeclDirectiveListParserHelper Helper(this, DKind);
2792 if (!ParseOpenMPSimpleVarList(Kind: DKind, Callback: Helper,
2793 /*AllowScopeSpecifier=*/false)) {
2794 SmallVector<OMPClause *, 1> Clauses;
2795 if (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2796 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2797 while (Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2798 OpenMPClauseKind CKind =
2799 Tok.isAnnotation() ? OMPC_unknown
2800 : getOpenMPClauseKind(Str: PP.getSpelling(Tok));
2801 Actions.OpenMP().StartOpenMPClause(K: CKind);
2802 OMPClause *Clause = ParseOpenMPClause(DKind: OMPD_allocate, CKind,
2803 FirstClause: !SeenClauses[unsigned(CKind)]);
2804 SkipUntil(T1: tok::comma, T2: tok::identifier, T3: tok::annot_pragma_openmp_end,
2805 Flags: StopBeforeMatch);
2806 SeenClauses[unsigned(CKind)] = true;
2807 if (Clause != nullptr)
2808 Clauses.push_back(Elt: Clause);
2809 if (Tok.is(K: tok::annot_pragma_openmp_end)) {
2810 Actions.OpenMP().EndOpenMPClause();
2811 break;
2812 }
2813 // Skip ',' if any.
2814 if (Tok.is(K: tok::comma))
2815 ConsumeToken();
2816 Actions.OpenMP().EndOpenMPClause();
2817 }
2818 skipUntilPragmaOpenMPEnd(DKind);
2819 }
2820 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
2821 Loc, VarList: Helper.getIdentifiers(), Clauses);
2822 Directive = Actions.ActOnDeclStmt(Decl: Res, StartLoc: Loc, EndLoc: Tok.getLocation());
2823 }
2824 SkipUntil(T: tok::annot_pragma_openmp_end);
2825 break;
2826 }
2827 case OMPD_declare_reduction:
2828 ConsumeToken();
2829 if (DeclGroupPtrTy Res =
2830 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2831 skipUntilPragmaOpenMPEnd(DKind: OMPD_declare_reduction);
2832 ConsumeAnyToken();
2833 Directive = Actions.ActOnDeclStmt(Decl: Res, StartLoc: Loc, EndLoc: Tok.getLocation());
2834 } else {
2835 SkipUntil(T: tok::annot_pragma_openmp_end);
2836 }
2837 break;
2838 case OMPD_declare_mapper: {
2839 ConsumeToken();
2840 if (DeclGroupPtrTy Res =
2841 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2842 // Skip the last annot_pragma_openmp_end.
2843 ConsumeAnnotationToken();
2844 Directive = Actions.ActOnDeclStmt(Decl: Res, StartLoc: Loc, EndLoc: Tok.getLocation());
2845 } else {
2846 SkipUntil(T: tok::annot_pragma_openmp_end);
2847 }
2848 break;
2849 }
2850 case OMPD_declare_target: {
2851 SourceLocation DTLoc = ConsumeAnyToken();
2852 bool HasClauses = Tok.isNot(K: tok::annot_pragma_openmp_end);
2853 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2854 if (HasClauses)
2855 ParseOMPDeclareTargetClauses(DTCI);
2856 bool HasImplicitMappings =
2857 !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2858
2859 if (HasImplicitMappings) {
2860 Diag(Tok, DiagID: diag::err_omp_unexpected_directive)
2861 << 1 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
2862 SkipUntil(T: tok::annot_pragma_openmp_end);
2863 break;
2864 }
2865
2866 // Skip the last annot_pragma_openmp_end.
2867 ConsumeAnyToken();
2868
2869 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2870 break;
2871 }
2872 case OMPD_begin_declare_variant: {
2873 ConsumeToken();
2874 if (!ParseOpenMPDeclareBeginVariantDirective(Loc)) {
2875 // Skip the last annot_pragma_openmp_end.
2876 if (!isEofOrEom())
2877 ConsumeAnnotationToken();
2878 }
2879 return Directive;
2880 }
2881 case OMPD_end_declare_variant: {
2882 ConsumeToken();
2883 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2884 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2885 else
2886 Diag(Loc, DiagID: diag::err_expected_begin_declare_variant);
2887 ConsumeAnnotationToken();
2888 break;
2889 }
2890 case OMPD_declare_simd:
2891 case OMPD_begin_declare_target:
2892 case OMPD_end_declare_target:
2893 case OMPD_requires:
2894 case OMPD_declare_variant:
2895 Diag(Tok, DiagID: diag::err_omp_unexpected_directive)
2896 << 1 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
2897 SkipUntil(T: tok::annot_pragma_openmp_end);
2898 break;
2899 case OMPD_assume: {
2900 ConsumeToken();
2901 Directive = ParseOpenMPInformationalDirective(
2902 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2903 assert(!Directive.isUnset() &&
2904 "Informational directive remains unprocessed");
2905 return Directive;
2906 }
2907 case OMPD_unknown:
2908 default:
2909 Diag(Tok, DiagID: diag::err_omp_unknown_directive);
2910 SkipUntil(T: tok::annot_pragma_openmp_end);
2911 break;
2912 }
2913 return Directive;
2914}
2915
2916bool Parser::ParseOpenMPSimpleVarList(
2917 OpenMPDirectiveKind Kind,
2918 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
2919 &Callback,
2920 bool AllowScopeSpecifier) {
2921 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
2922 // Parse '('.
2923 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2924 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after,
2925 Msg: getOpenMPDirectiveName(D: Kind, Ver: OMPVersion).data()))
2926 return true;
2927 bool IsCorrect = true;
2928 bool NoIdentIsFound = true;
2929
2930 // Read tokens while ')' or annot_pragma_openmp_end is not found.
2931 while (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2932 CXXScopeSpec SS;
2933 UnqualifiedId Name;
2934 // Read var name.
2935 Token PrevTok = Tok;
2936 NoIdentIsFound = false;
2937
2938 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2939 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2940 /*ObjectHasErrors=*/false, EnteringContext: false)) {
2941 IsCorrect = false;
2942 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
2943 Flags: StopBeforeMatch);
2944 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2945 /*ObjectHadErrors=*/false, EnteringContext: false, AllowDestructorName: false,
2946 AllowConstructorName: false, AllowDeductionGuide: false, TemplateKWLoc: nullptr, Result&: Name)) {
2947 IsCorrect = false;
2948 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
2949 Flags: StopBeforeMatch);
2950 } else if (Tok.isNot(K: tok::comma) && Tok.isNot(K: tok::r_paren) &&
2951 Tok.isNot(K: tok::annot_pragma_openmp_end)) {
2952 IsCorrect = false;
2953 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
2954 Flags: StopBeforeMatch);
2955 Diag(Loc: PrevTok.getLocation(), DiagID: diag::err_expected)
2956 << tok::identifier
2957 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2958 } else {
2959 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2960 }
2961 // Consume ','.
2962 if (Tok.is(K: tok::comma)) {
2963 ConsumeToken();
2964 }
2965 }
2966
2967 if (NoIdentIsFound) {
2968 Diag(Tok, DiagID: diag::err_expected) << tok::identifier;
2969 IsCorrect = false;
2970 }
2971
2972 // Parse ')'.
2973 IsCorrect = !T.consumeClose() && IsCorrect;
2974
2975 return !IsCorrect;
2976}
2977
2978OMPClause *Parser::ParseOpenMPSizesClause() {
2979 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
2980 SmallVector<Expr *, 4> ValExprs;
2981 if (ParseOpenMPExprListClause(Kind: OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
2982 Exprs&: ValExprs))
2983 return nullptr;
2984
2985 return Actions.OpenMP().ActOnOpenMPSizesClause(SizeExprs: ValExprs, StartLoc: ClauseNameLoc,
2986 LParenLoc: OpenLoc, EndLoc: CloseLoc);
2987}
2988
2989OMPClause *Parser::ParseOpenMPLoopRangeClause() {
2990 SourceLocation ClauseNameLoc = ConsumeToken();
2991 SourceLocation FirstLoc, CountLoc;
2992
2993 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2994 if (T.consumeOpen()) {
2995 Diag(Tok, DiagID: diag::err_expected) << tok::l_paren;
2996 return nullptr;
2997 }
2998
2999 FirstLoc = Tok.getLocation();
3000 ExprResult FirstVal = ParseConstantExpression();
3001 if (!FirstVal.isUsable()) {
3002 T.skipToEnd();
3003 return nullptr;
3004 }
3005
3006 ExpectAndConsume(ExpectedTok: tok::comma);
3007
3008 CountLoc = Tok.getLocation();
3009 ExprResult CountVal = ParseConstantExpression();
3010 if (!CountVal.isUsable()) {
3011 T.skipToEnd();
3012 return nullptr;
3013 }
3014
3015 T.consumeClose();
3016
3017 return Actions.OpenMP().ActOnOpenMPLoopRangeClause(
3018 First: FirstVal.get(), Count: CountVal.get(), StartLoc: ClauseNameLoc, LParenLoc: T.getOpenLocation(),
3019 FirstLoc, CountLoc, EndLoc: T.getCloseLocation());
3020}
3021
3022OMPClause *Parser::ParseOpenMPPermutationClause() {
3023 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3024 SmallVector<Expr *> ArgExprs;
3025 if (ParseOpenMPExprListClause(Kind: OMPC_permutation, ClauseNameLoc, OpenLoc,
3026 CloseLoc, Exprs&: ArgExprs,
3027 /*ReqIntConst=*/true))
3028 return nullptr;
3029
3030 return Actions.OpenMP().ActOnOpenMPPermutationClause(PermExprs: ArgExprs, StartLoc: ClauseNameLoc,
3031 LParenLoc: OpenLoc, EndLoc: CloseLoc);
3032}
3033
3034OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
3035 SourceLocation Loc = Tok.getLocation();
3036 ConsumeAnyToken();
3037
3038 // Parse '('.
3039 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3040 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after, Msg: "uses_allocator"))
3041 return nullptr;
3042 SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
3043 do {
3044 // Parse 'traits(expr) : Allocator' for >=5.2
3045 if (getLangOpts().OpenMP >= 52 && Tok.is(K: tok::identifier) &&
3046 Tok.getIdentifierInfo()->getName() == "traits") {
3047
3048 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3049
3050 ConsumeToken();
3051
3052 // Parse '(' <expr> ')'
3053 BalancedDelimiterTracker TraitParens(*this, tok::l_paren,
3054 tok::annot_pragma_openmp_end);
3055 TraitParens.consumeOpen();
3056 ExprResult AllocatorTraits =
3057 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3058 TraitParens.consumeClose();
3059
3060 if (AllocatorTraits.isInvalid()) {
3061 SkipUntil(
3062 Toks: {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3063 Flags: StopBeforeMatch);
3064 break;
3065 }
3066
3067 // Expect ':'
3068 if (Tok.isNot(K: tok::colon)) {
3069 Diag(Tok, DiagID: diag::err_expected) << tok::colon;
3070 SkipUntil(
3071 Toks: {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3072 Flags: StopBeforeMatch);
3073 continue;
3074 }
3075 ConsumeToken();
3076
3077 CXXScopeSpec SS;
3078 Token Replacement;
3079 ExprResult AllocatorExpr =
3080 getLangOpts().CPlusPlus
3081 ? ParseCXXIdExpression()
3082 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
3083 Replacement);
3084
3085 if (AllocatorExpr.isInvalid()) {
3086 SkipUntil(
3087 Toks: {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
3088 Flags: StopBeforeMatch);
3089 break;
3090 }
3091
3092 D.Allocator = AllocatorExpr.get();
3093 D.AllocatorTraits = AllocatorTraits.get();
3094 D.LParenLoc = TraitParens.getOpenLocation();
3095 D.RParenLoc = TraitParens.getCloseLocation();
3096
3097 // Separator handling(;)
3098 if (Tok.is(K: tok::comma)) {
3099 // In 5.2, comma is invalid
3100 Diag(Loc: Tok.getLocation(), DiagID: diag::err_omp_allocator_comma_separator)
3101 << FixItHint::CreateReplacement(RemoveRange: Tok.getLocation(), Code: ";");
3102 ConsumeAnyToken();
3103 } else if (Tok.is(K: tok::semi)) {
3104 ConsumeAnyToken(); // valid separator
3105 }
3106
3107 continue;
3108 }
3109
3110 // Parse 'Allocator(expr)' for <5.2
3111 CXXScopeSpec SS;
3112 Token Replacement;
3113 ExprResult Allocator =
3114 getLangOpts().CPlusPlus
3115 ? ParseCXXIdExpression()
3116 : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
3117 Replacement);
3118 if (Allocator.isInvalid()) {
3119 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
3120 Flags: StopBeforeMatch);
3121 break;
3122 }
3123 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3124 D.Allocator = Allocator.get();
3125 if (Tok.is(K: tok::l_paren)) {
3126 BalancedDelimiterTracker T(*this, tok::l_paren,
3127 tok::annot_pragma_openmp_end);
3128 T.consumeOpen();
3129 ExprResult AllocatorTraits =
3130 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3131 T.consumeClose();
3132 if (AllocatorTraits.isInvalid()) {
3133 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
3134 Flags: StopBeforeMatch);
3135 break;
3136 }
3137 D.AllocatorTraits = AllocatorTraits.get();
3138 D.LParenLoc = T.getOpenLocation();
3139 D.RParenLoc = T.getCloseLocation();
3140
3141 // Deprecation diagnostic in >= 5.2
3142 if (getLangOpts().OpenMP >= 52) {
3143 Diag(Loc, DiagID: diag::err_omp_deprecate_old_syntax)
3144 << "allocator(expr)" // %0: old form
3145 << "uses_allocators" // %1: clause name
3146 << "traits(expr): alloc"; // %2: suggested new form
3147 }
3148 }
3149 if (Tok.isNot(K: tok::comma) && Tok.isNot(K: tok::r_paren))
3150 Diag(Tok, DiagID: diag::err_omp_expected_punc) << "uses_allocators" << 0;
3151 // Parse ','
3152 if (Tok.is(K: tok::comma))
3153 ConsumeAnyToken();
3154 } while (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::annot_pragma_openmp_end));
3155 T.consumeClose();
3156 return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3157 StartLoc: Loc, LParenLoc: T.getOpenLocation(), EndLoc: T.getCloseLocation(), Data);
3158}
3159
3160OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
3161 OpenMPClauseKind CKind, bool FirstClause) {
3162 OMPClauseKind = CKind;
3163 OMPClause *Clause = nullptr;
3164 bool ErrorFound = false;
3165 bool WrongDirective = false;
3166 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
3167
3168 // Check if clause is allowed for the given directive.
3169 if (CKind != OMPC_unknown &&
3170 !isAllowedClauseForDirective(D: DKind, C: CKind, Version: getLangOpts().OpenMP)) {
3171 Diag(Tok, DiagID: diag::err_omp_unexpected_clause)
3172 << getOpenMPClauseName(C: CKind)
3173 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3174 ErrorFound = true;
3175 WrongDirective = true;
3176 }
3177
3178 switch (CKind) {
3179 case OMPC_final:
3180 case OMPC_num_threads:
3181 case OMPC_safelen:
3182 case OMPC_simdlen:
3183 case OMPC_collapse:
3184 case OMPC_ordered:
3185 case OMPC_priority:
3186 case OMPC_grainsize:
3187 case OMPC_num_tasks:
3188 case OMPC_hint:
3189 case OMPC_allocator:
3190 case OMPC_depobj:
3191 case OMPC_detach:
3192 case OMPC_novariants:
3193 case OMPC_nocontext:
3194 case OMPC_filter:
3195 case OMPC_partial:
3196 case OMPC_align:
3197 case OMPC_message:
3198 case OMPC_ompx_dyn_cgroup_mem:
3199 case OMPC_dyn_groupprivate:
3200 case OMPC_transparent:
3201 // OpenMP [2.5, Restrictions]
3202 // At most one num_threads clause can appear on the directive.
3203 // OpenMP [2.8.1, simd construct, Restrictions]
3204 // Only one safelen clause can appear on a simd directive.
3205 // Only one simdlen clause can appear on a simd directive.
3206 // Only one collapse clause can appear on a simd directive.
3207 // OpenMP [2.11.1, task Construct, Restrictions]
3208 // At most one if clause can appear on the directive.
3209 // At most one final clause can appear on the directive.
3210 // OpenMP [teams Construct, Restrictions]
3211 // At most one num_teams clause can appear on the directive.
3212 // At most one thread_limit clause can appear on the directive.
3213 // OpenMP [2.9.1, task Construct, Restrictions]
3214 // At most one priority clause can appear on the directive.
3215 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3216 // At most one grainsize clause can appear on the directive.
3217 // OpenMP [2.9.2, taskloop Construct, Restrictions]
3218 // At most one num_tasks clause can appear on the directive.
3219 // OpenMP [2.11.3, allocate Directive, Restrictions]
3220 // At most one allocator clause can appear on the directive.
3221 // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3222 // At most one detach clause can appear on the directive.
3223 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3224 // At most one novariants clause can appear on a dispatch directive.
3225 // At most one nocontext clause can appear on a dispatch directive.
3226 // OpenMP [5.1, error directive, Restrictions]
3227 // At most one message clause can appear on the directive
3228 if (!FirstClause) {
3229 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3230 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3231 << getOpenMPClauseName(C: CKind) << 0;
3232 ErrorFound = true;
3233 }
3234
3235 if (CKind == OMPC_transparent && PP.LookAhead(N: 0).isNot(K: tok::l_paren)) {
3236 SourceLocation Loc = ConsumeToken();
3237 SourceLocation LLoc = Tok.getLocation();
3238 Clause = Actions.OpenMP().ActOnOpenMPTransparentClause(Transparent: nullptr, StartLoc: LLoc,
3239 LParenLoc: LLoc, EndLoc: Loc);
3240 break;
3241 }
3242 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3243 PP.LookAhead(/*N=*/0).isNot(K: tok::l_paren))
3244 Clause = ParseOpenMPClause(Kind: CKind, ParseOnly: WrongDirective);
3245 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||
3246 CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate)
3247 Clause = ParseOpenMPSingleExprWithArgClause(DKind, Kind: CKind, ParseOnly: WrongDirective);
3248 else
3249 Clause = ParseOpenMPSingleExprClause(Kind: CKind, ParseOnly: WrongDirective);
3250 break;
3251 case OMPC_threadset:
3252 case OMPC_fail:
3253 case OMPC_proc_bind:
3254 case OMPC_atomic_default_mem_order:
3255 case OMPC_at:
3256 case OMPC_severity:
3257 case OMPC_bind:
3258 // OpenMP [2.14.3.1, Restrictions]
3259 // Only a single default clause may be specified on a parallel, task or
3260 // teams directive.
3261 // OpenMP [2.5, parallel Construct, Restrictions]
3262 // At most one proc_bind clause can appear on the directive.
3263 // OpenMP [5.0, Requires directive, Restrictions]
3264 // At most one atomic_default_mem_order clause can appear
3265 // on the directive
3266 // OpenMP [5.1, error directive, Restrictions]
3267 // At most one at clause can appear on the directive
3268 // At most one severity clause can appear on the directive
3269 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3270 // At most one bind clause can appear on a loop directive.
3271 if (!FirstClause) {
3272 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3273 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3274 << getOpenMPClauseName(C: CKind) << 0;
3275 ErrorFound = true;
3276 }
3277
3278 Clause = ParseOpenMPSimpleClause(Kind: CKind, ParseOnly: WrongDirective);
3279 break;
3280 case OMPC_device:
3281 case OMPC_schedule:
3282 case OMPC_dist_schedule:
3283 case OMPC_defaultmap:
3284 case OMPC_default:
3285 case OMPC_order:
3286 // OpenMP [2.7.1, Restrictions, p. 3]
3287 // Only one schedule clause can appear on a loop directive.
3288 // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3289 // At most one defaultmap clause can appear on the directive.
3290 // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3291 // At most one device clause can appear on the directive.
3292 // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3293 // At most one order clause may appear on a construct.
3294 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3295 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3296 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3297 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3298 << getOpenMPClauseName(C: CKind) << 0;
3299 ErrorFound = true;
3300 }
3301 [[fallthrough]];
3302 case OMPC_if:
3303 Clause = ParseOpenMPSingleExprWithArgClause(DKind, Kind: CKind, ParseOnly: WrongDirective);
3304 break;
3305 case OMPC_holds:
3306 Clause = ParseOpenMPSingleExprClause(Kind: CKind, ParseOnly: WrongDirective);
3307 break;
3308 case OMPC_nowait:
3309 case OMPC_untied:
3310 case OMPC_mergeable:
3311 case OMPC_read:
3312 case OMPC_write:
3313 case OMPC_capture:
3314 case OMPC_compare:
3315 case OMPC_seq_cst:
3316 case OMPC_acq_rel:
3317 case OMPC_acquire:
3318 case OMPC_release:
3319 case OMPC_relaxed:
3320 case OMPC_weak:
3321 case OMPC_threads:
3322 case OMPC_simd:
3323 case OMPC_nogroup:
3324 case OMPC_unified_address:
3325 case OMPC_unified_shared_memory:
3326 case OMPC_reverse_offload:
3327 case OMPC_dynamic_allocators:
3328 case OMPC_full:
3329 // OpenMP [2.7.1, Restrictions, p. 9]
3330 // Only one ordered clause can appear on a loop directive.
3331 // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3332 // Only one nowait clause can appear on a for directive.
3333 // OpenMP [5.0, Requires directive, Restrictions]
3334 // Each of the requires clauses can appear at most once on the directive.
3335 if (!FirstClause) {
3336 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3337 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3338 << getOpenMPClauseName(C: CKind) << 0;
3339 ErrorFound = true;
3340 }
3341
3342 if (CKind == OMPC_nowait && PP.LookAhead(/*N=*/0).is(K: tok::l_paren) &&
3343 getLangOpts().OpenMP >= 60)
3344 Clause = ParseOpenMPSingleExprClause(Kind: CKind, ParseOnly: WrongDirective);
3345 else
3346 Clause = ParseOpenMPClause(Kind: CKind, ParseOnly: WrongDirective);
3347 break;
3348 case OMPC_self_maps:
3349 // OpenMP [6.0, self_maps clause]
3350 if (getLangOpts().OpenMP < 60) {
3351 Diag(Tok, DiagID: diag::err_omp_expected_clause)
3352 << getOpenMPDirectiveName(D: OMPD_requires, Ver: OMPVersion);
3353 ErrorFound = true;
3354 }
3355 if (!FirstClause) {
3356 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3357 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3358 << getOpenMPClauseName(C: CKind) << 0;
3359 ErrorFound = true;
3360 }
3361 Clause = ParseOpenMPClause(Kind: CKind, ParseOnly: WrongDirective);
3362 break;
3363 case OMPC_update:
3364 if (!FirstClause) {
3365 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3366 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3367 << getOpenMPClauseName(C: CKind) << 0;
3368 ErrorFound = true;
3369 }
3370
3371 Clause = (DKind == OMPD_depobj)
3372 ? ParseOpenMPSimpleClause(Kind: CKind, ParseOnly: WrongDirective)
3373 : ParseOpenMPClause(Kind: CKind, ParseOnly: WrongDirective);
3374 break;
3375 case OMPC_num_teams:
3376 case OMPC_thread_limit:
3377 if (!FirstClause) {
3378 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3379 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3380 << getOpenMPClauseName(C: CKind) << 0;
3381 ErrorFound = true;
3382 }
3383 [[fallthrough]];
3384 case OMPC_private:
3385 case OMPC_firstprivate:
3386 case OMPC_lastprivate:
3387 case OMPC_shared:
3388 case OMPC_reduction:
3389 case OMPC_task_reduction:
3390 case OMPC_in_reduction:
3391 case OMPC_linear:
3392 case OMPC_aligned:
3393 case OMPC_copyin:
3394 case OMPC_copyprivate:
3395 case OMPC_flush:
3396 case OMPC_depend:
3397 case OMPC_map:
3398 case OMPC_to:
3399 case OMPC_from:
3400 case OMPC_use_device_ptr:
3401 case OMPC_use_device_addr:
3402 case OMPC_is_device_ptr:
3403 case OMPC_has_device_addr:
3404 case OMPC_allocate:
3405 case OMPC_nontemporal:
3406 case OMPC_inclusive:
3407 case OMPC_exclusive:
3408 case OMPC_affinity:
3409 case OMPC_doacross:
3410 case OMPC_enter:
3411 if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
3412 CKind == OMPC_depend)
3413 Diag(Tok, DiagID: diag::warn_omp_depend_in_ordered_deprecated);
3414 Clause = ParseOpenMPVarListClause(DKind, Kind: CKind, ParseOnly: WrongDirective);
3415 break;
3416 case OMPC_sizes:
3417 if (!FirstClause) {
3418 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3419 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3420 << getOpenMPClauseName(C: CKind) << 0;
3421 ErrorFound = true;
3422 }
3423
3424 Clause = ParseOpenMPSizesClause();
3425 break;
3426 case OMPC_permutation:
3427 if (!FirstClause) {
3428 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3429 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3430 << getOpenMPClauseName(C: CKind) << 0;
3431 ErrorFound = true;
3432 }
3433 Clause = ParseOpenMPPermutationClause();
3434 break;
3435 case OMPC_uses_allocators:
3436 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3437 break;
3438 case OMPC_destroy:
3439 if (DKind != OMPD_interop) {
3440 if (!FirstClause) {
3441 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3442 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3443 << getOpenMPClauseName(C: CKind) << 0;
3444 ErrorFound = true;
3445 }
3446 Clause = ParseOpenMPClause(Kind: CKind, ParseOnly: WrongDirective);
3447 break;
3448 }
3449 [[fallthrough]];
3450 case OMPC_init:
3451 case OMPC_use:
3452 Clause = ParseOpenMPInteropClause(Kind: CKind, ParseOnly: WrongDirective);
3453 break;
3454 case OMPC_device_type:
3455 case OMPC_unknown:
3456 skipUntilPragmaOpenMPEnd(DKind);
3457 break;
3458 case OMPC_threadprivate:
3459 case OMPC_groupprivate:
3460 case OMPC_uniform:
3461 case OMPC_match:
3462 if (!WrongDirective)
3463 Diag(Tok, DiagID: diag::err_omp_unexpected_clause)
3464 << getOpenMPClauseName(C: CKind)
3465 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3466 SkipUntil(T1: tok::comma, T2: tok::annot_pragma_openmp_end, Flags: StopBeforeMatch);
3467 break;
3468 case OMPC_absent:
3469 case OMPC_contains: {
3470 SourceLocation Loc = ConsumeToken();
3471 SourceLocation LLoc = Tok.getLocation();
3472 SourceLocation RLoc;
3473 llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
3474 BalancedDelimiterTracker T(*this, tok::l_paren);
3475 T.consumeOpen();
3476 do {
3477 OpenMPDirectiveKind DK = getOpenMPDirectiveKind(Str: PP.getSpelling(Tok));
3478 if (DK == OMPD_unknown) {
3479 skipUntilPragmaOpenMPEnd(DKind: OMPD_assume);
3480 Diag(Tok, DiagID: diag::err_omp_unexpected_clause)
3481 << getOpenMPClauseName(C: CKind)
3482 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3483 break;
3484 }
3485 if (isOpenMPExecutableDirective(DKind: DK)) {
3486 DKVec.push_back(Elt: DK);
3487 ConsumeToken();
3488 } else {
3489 Diag(Tok, DiagID: diag::err_omp_unexpected_clause)
3490 << getOpenMPClauseName(C: CKind)
3491 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3492 }
3493 } while (TryConsumeToken(Expected: tok::comma));
3494 RLoc = Tok.getLocation();
3495 T.consumeClose();
3496 Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
3497 CK: CKind, DKVec, Loc, LLoc, RLoc);
3498 break;
3499 }
3500 case OMPC_no_openmp:
3501 case OMPC_no_openmp_routines:
3502 case OMPC_no_openmp_constructs:
3503 case OMPC_no_parallelism: {
3504 if (!FirstClause) {
3505 Diag(Tok, DiagID: diag::err_omp_more_one_clause)
3506 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion)
3507 << getOpenMPClauseName(C: CKind) << 0;
3508 ErrorFound = true;
3509 }
3510 SourceLocation Loc = ConsumeToken();
3511 Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
3512 CK: CKind, Loc, RLoc: Tok.getLocation());
3513 break;
3514 }
3515 case OMPC_ompx_attribute:
3516 Clause = ParseOpenMPOMPXAttributesClause(ParseOnly: WrongDirective);
3517 break;
3518 case OMPC_ompx_bare:
3519 if (DKind == llvm::omp::Directive::OMPD_target) {
3520 // Flang splits the combined directives which requires OMPD_target to be
3521 // marked as accepting the `ompx_bare` clause in `OMP.td`. Thus, we need
3522 // to explicitly check whether this clause is applied to an `omp target`
3523 // without `teams` and emit an error.
3524 Diag(Tok, DiagID: diag::err_omp_unexpected_clause)
3525 << getOpenMPClauseName(C: CKind)
3526 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3527 ErrorFound = true;
3528 WrongDirective = true;
3529 }
3530 if (WrongDirective)
3531 Diag(Tok, DiagID: diag::note_ompx_bare_clause)
3532 << getOpenMPClauseName(C: CKind) << "target teams";
3533 if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3534 Diag(Tok, DiagID: diag::err_omp_unexpected_clause_extension_only)
3535 << getOpenMPClauseName(C: CKind)
3536 << getOpenMPDirectiveName(D: DKind, Ver: OMPVersion);
3537 ErrorFound = true;
3538 }
3539 Clause = ParseOpenMPClause(Kind: CKind, ParseOnly: WrongDirective);
3540 break;
3541 case OMPC_looprange:
3542 Clause = ParseOpenMPLoopRangeClause();
3543 break;
3544 default:
3545 break;
3546 }
3547 return ErrorFound ? nullptr : Clause;
3548}
3549
3550/// Parses simple expression in parens for single-expression clauses of OpenMP
3551/// constructs.
3552/// \param RLoc Returned location of right paren.
3553ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
3554 SourceLocation &RLoc,
3555 bool IsAddressOfOperand) {
3556 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3557 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after, Msg: ClauseName.data()))
3558 return ExprError();
3559
3560 SourceLocation ELoc = Tok.getLocation();
3561 ExprResult LHS(
3562 ParseCastExpression(ParseKind: CastParseKind::AnyCastExpr, isAddressOfOperand: IsAddressOfOperand,
3563 CorrectionBehavior: TypoCorrectionTypeBehavior::AllowNonTypes));
3564 ExprResult Val(ParseRHSOfBinaryExpression(LHS, MinPrec: prec::Conditional));
3565 Val = Actions.ActOnFinishFullExpr(Expr: Val.get(), CC: ELoc, /*DiscardedValue*/ false);
3566
3567 // Parse ')'.
3568 RLoc = Tok.getLocation();
3569 if (!T.consumeClose())
3570 RLoc = T.getCloseLocation();
3571
3572 return Val;
3573}
3574
3575OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3576 bool ParseOnly) {
3577 SourceLocation Loc = ConsumeToken();
3578 SourceLocation LLoc = Tok.getLocation();
3579 SourceLocation RLoc;
3580
3581 ExprResult Val = ParseOpenMPParensExpr(ClauseName: getOpenMPClauseName(C: Kind), RLoc);
3582
3583 if (Val.isInvalid())
3584 return nullptr;
3585
3586 if (ParseOnly)
3587 return nullptr;
3588 return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Expr: Val.get(), StartLoc: Loc,
3589 LParenLoc: LLoc, EndLoc: RLoc);
3590}
3591
3592bool Parser::ParseOpenMPIndirectClause(
3593 SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3594 SourceLocation Loc = ConsumeToken();
3595 SourceLocation RLoc;
3596
3597 if (Tok.isNot(K: tok::l_paren)) {
3598 if (ParseOnly)
3599 return false;
3600 DTCI.Indirect = nullptr;
3601 return true;
3602 }
3603
3604 ExprResult Val =
3605 ParseOpenMPParensExpr(ClauseName: getOpenMPClauseName(C: OMPC_indirect), RLoc);
3606 if (Val.isInvalid())
3607 return false;
3608
3609 if (ParseOnly)
3610 return false;
3611
3612 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3613 !Val.get()->isInstantiationDependent() &&
3614 !Val.get()->containsUnexpandedParameterPack()) {
3615 ExprResult Ret = Actions.CheckBooleanCondition(Loc, E: Val.get());
3616 if (Ret.isInvalid())
3617 return false;
3618 llvm::APSInt Result;
3619 Ret = Actions.VerifyIntegerConstantExpression(E: Val.get(), Result: &Result,
3620 CanFold: AllowFoldKind::Allow);
3621 if (Ret.isInvalid())
3622 return false;
3623 DTCI.Indirect = Val.get();
3624 return true;
3625 }
3626 return false;
3627}
3628
3629bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3630 OpenMPClauseKind Kind) {
3631 const Token &Tok = getCurToken();
3632 bool HasError = false;
3633 bool IsTarget = false;
3634 bool IsTargetSync = false;
3635
3636 while (Tok.is(K: tok::identifier)) {
3637 // Currently prefer_type is only allowed with 'init' and it must be first.
3638 bool PreferTypeAllowed = Kind == OMPC_init &&
3639 InteropInfo.PreferTypes.empty() && !IsTarget &&
3640 !IsTargetSync;
3641 if (Tok.getIdentifierInfo()->isStr(Str: "target")) {
3642 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3643 // Each interop-type may be specified on an action-clause at most
3644 // once.
3645 if (IsTarget)
3646 Diag(Tok, DiagID: diag::warn_omp_more_one_interop_type) << "target";
3647 IsTarget = true;
3648 ConsumeToken();
3649 } else if (Tok.getIdentifierInfo()->isStr(Str: "targetsync")) {
3650 if (IsTargetSync)
3651 Diag(Tok, DiagID: diag::warn_omp_more_one_interop_type) << "targetsync";
3652 IsTargetSync = true;
3653 ConsumeToken();
3654 } else if (Tok.getIdentifierInfo()->isStr(Str: "prefer_type") &&
3655 PreferTypeAllowed) {
3656 ConsumeToken();
3657 BalancedDelimiterTracker PT(*this, tok::l_paren,
3658 tok::annot_pragma_openmp_end);
3659 if (PT.expectAndConsume(DiagID: diag::err_expected_lparen_after, Msg: "prefer_type"))
3660 HasError = true;
3661
3662 while (Tok.isNot(K: tok::r_paren)) {
3663 SourceLocation Loc = Tok.getLocation();
3664 ExprResult LHS = ParseCastExpression(ParseKind: CastParseKind::AnyCastExpr);
3665 ExprResult PTExpr = ParseRHSOfBinaryExpression(LHS, MinPrec: prec::Conditional);
3666 PTExpr = Actions.ActOnFinishFullExpr(Expr: PTExpr.get(), CC: Loc,
3667 /*DiscardedValue=*/false);
3668 if (PTExpr.isUsable()) {
3669 InteropInfo.PreferTypes.push_back(Elt: PTExpr.get());
3670 } else {
3671 HasError = true;
3672 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
3673 Flags: StopBeforeMatch);
3674 }
3675
3676 if (Tok.is(K: tok::comma))
3677 ConsumeToken();
3678 }
3679 PT.consumeClose();
3680 } else {
3681 HasError = true;
3682 Diag(Tok, DiagID: diag::err_omp_expected_interop_type);
3683 ConsumeToken();
3684 }
3685 if (!Tok.is(K: tok::comma))
3686 break;
3687 ConsumeToken();
3688 }
3689
3690 if (!HasError && !IsTarget && !IsTargetSync) {
3691 Diag(Tok, DiagID: diag::err_omp_expected_interop_type);
3692 HasError = true;
3693 }
3694
3695 if (Kind == OMPC_init) {
3696 if (Tok.isNot(K: tok::colon) && (IsTarget || IsTargetSync))
3697 Diag(Tok, DiagID: diag::warn_pragma_expected_colon) << "interop types";
3698 if (Tok.is(K: tok::colon))
3699 ConsumeToken();
3700 }
3701
3702 // As of OpenMP 5.1,there are two interop-types, "target" and
3703 // "targetsync". Either or both are allowed for a single interop.
3704 InteropInfo.IsTarget = IsTarget;
3705 InteropInfo.IsTargetSync = IsTargetSync;
3706
3707 return HasError;
3708}
3709
3710OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3711 bool ParseOnly) {
3712 SourceLocation Loc = ConsumeToken();
3713 // Parse '('.
3714 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3715 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after,
3716 Msg: getOpenMPClauseName(C: Kind).data()))
3717 return nullptr;
3718
3719 bool InteropError = false;
3720 OMPInteropInfo InteropInfo;
3721 if (Kind == OMPC_init)
3722 InteropError = ParseOMPInteropInfo(InteropInfo, Kind: OMPC_init);
3723
3724 // Parse the variable.
3725 SourceLocation VarLoc = Tok.getLocation();
3726 ExprResult InteropVarExpr = ParseAssignmentExpression();
3727 if (!InteropVarExpr.isUsable()) {
3728 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
3729 Flags: StopBeforeMatch);
3730 }
3731
3732 // Parse ')'.
3733 SourceLocation RLoc = Tok.getLocation();
3734 if (!T.consumeClose())
3735 RLoc = T.getCloseLocation();
3736
3737 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3738 return nullptr;
3739
3740 if (Kind == OMPC_init)
3741 return Actions.OpenMP().ActOnOpenMPInitClause(
3742 InteropVar: InteropVarExpr.get(), InteropInfo, StartLoc: Loc, LParenLoc: T.getOpenLocation(), VarLoc,
3743 EndLoc: RLoc);
3744 if (Kind == OMPC_use)
3745 return Actions.OpenMP().ActOnOpenMPUseClause(
3746 InteropVar: InteropVarExpr.get(), StartLoc: Loc, LParenLoc: T.getOpenLocation(), VarLoc, EndLoc: RLoc);
3747
3748 if (Kind == OMPC_destroy)
3749 return Actions.OpenMP().ActOnOpenMPDestroyClause(
3750 InteropVar: InteropVarExpr.get(), StartLoc: Loc, LParenLoc: T.getOpenLocation(), VarLoc, EndLoc: RLoc);
3751
3752 llvm_unreachable("Unexpected interop variable clause.");
3753}
3754
3755OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
3756 SourceLocation Loc = ConsumeToken();
3757 // Parse '('.
3758 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3759 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after,
3760 Msg: getOpenMPClauseName(C: OMPC_ompx_attribute).data()))
3761 return nullptr;
3762
3763 ParsedAttributes ParsedAttrs(AttrFactory);
3764 ParseAttributes(WhichAttrKinds: PAKM_GNU | PAKM_CXX11, Attrs&: ParsedAttrs);
3765
3766 // Parse ')'.
3767 if (T.consumeClose())
3768 return nullptr;
3769
3770 if (ParseOnly)
3771 return nullptr;
3772
3773 SmallVector<Attr *> Attrs;
3774 for (const ParsedAttr &PA : ParsedAttrs) {
3775 switch (PA.getKind()) {
3776 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
3777 if (!PA.checkExactlyNumArgs(S&: Actions, Num: 2))
3778 continue;
3779 if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
3780 CI: PA, Min: PA.getArgAsExpr(Arg: 0), Max: PA.getArgAsExpr(Arg: 1)))
3781 Attrs.push_back(Elt: A);
3782 continue;
3783 case ParsedAttr::AT_AMDGPUWavesPerEU:
3784 if (!PA.checkAtLeastNumArgs(S&: Actions, Num: 1) ||
3785 !PA.checkAtMostNumArgs(S&: Actions, Num: 2))
3786 continue;
3787 if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
3788 CI: PA, Min: PA.getArgAsExpr(Arg: 0),
3789 Max: PA.getNumArgs() > 1 ? PA.getArgAsExpr(Arg: 1) : nullptr))
3790 Attrs.push_back(Elt: A);
3791 continue;
3792 case ParsedAttr::AT_CUDALaunchBounds:
3793 if (!PA.checkAtLeastNumArgs(S&: Actions, Num: 1) ||
3794 !PA.checkAtMostNumArgs(S&: Actions, Num: 2))
3795 continue;
3796 if (auto *A = Actions.CreateLaunchBoundsAttr(
3797 CI: PA, MaxThreads: PA.getArgAsExpr(Arg: 0),
3798 MinBlocks: PA.getNumArgs() > 1 ? PA.getArgAsExpr(Arg: 1) : nullptr,
3799 MaxBlocks: PA.getNumArgs() > 2 ? PA.getArgAsExpr(Arg: 2) : nullptr))
3800 Attrs.push_back(Elt: A);
3801 continue;
3802 default:
3803 Diag(Loc, DiagID: diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3804 continue;
3805 };
3806 }
3807
3808 return Actions.OpenMP().ActOnOpenMPXAttributeClause(
3809 Attrs, StartLoc: Loc, LParenLoc: T.getOpenLocation(), EndLoc: T.getCloseLocation());
3810}
3811
3812OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
3813 bool ParseOnly) {
3814 std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(P&: *this, Kind);
3815 if (!Val || ParseOnly)
3816 return nullptr;
3817 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3818 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
3819 static_cast<DefaultKind>(Val->Type) ==
3820 OMP_DEFAULT_firstprivate)) {
3821 Diag(Loc: Val->LOpen, DiagID: diag::err_omp_invalid_dsa)
3822 << getOpenMPClauseName(C: static_cast<DefaultKind>(Val->Type) ==
3823 OMP_DEFAULT_private
3824 ? OMPC_private
3825 : OMPC_firstprivate)
3826 << getOpenMPClauseName(C: OMPC_default) << "5.1";
3827 return nullptr;
3828 }
3829 return Actions.OpenMP().ActOnOpenMPSimpleClause(
3830 Kind, Argument: Val->Type, ArgumentLoc: Val->TypeLoc, StartLoc: Val->LOpen, LParenLoc: Val->Loc, EndLoc: Val->RLoc);
3831}
3832
3833OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
3834 SourceLocation Loc = Tok.getLocation();
3835 ConsumeAnyToken();
3836
3837 if (ParseOnly)
3838 return nullptr;
3839 return Actions.OpenMP().ActOnOpenMPClause(Kind, StartLoc: Loc, EndLoc: Tok.getLocation());
3840}
3841
3842OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
3843 OpenMPClauseKind Kind,
3844 bool ParseOnly) {
3845 SourceLocation Loc = ConsumeToken();
3846 SourceLocation DelimLoc;
3847 // Parse '('.
3848 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3849 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after,
3850 Msg: getOpenMPClauseName(C: Kind).data()))
3851 return nullptr;
3852
3853 ExprResult Val;
3854 SmallVector<unsigned, 4> Arg;
3855 SmallVector<SourceLocation, 4> KLoc;
3856 if (Kind == OMPC_schedule) {
3857 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3858 Arg.resize(N: NumberOfElements);
3859 KLoc.resize(N: NumberOfElements);
3860 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
3861 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
3862 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
3863 unsigned KindModifier = getOpenMPSimpleClauseType(
3864 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
3865 if (KindModifier > OMPC_SCHEDULE_unknown) {
3866 // Parse 'modifier'
3867 Arg[Modifier1] = KindModifier;
3868 KLoc[Modifier1] = Tok.getLocation();
3869 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3870 Tok.isNot(K: tok::annot_pragma_openmp_end))
3871 ConsumeAnyToken();
3872 if (Tok.is(K: tok::comma)) {
3873 // Parse ',' 'modifier'
3874 ConsumeAnyToken();
3875 KindModifier = getOpenMPSimpleClauseType(
3876 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
3877 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
3878 ? KindModifier
3879 : (unsigned)OMPC_SCHEDULE_unknown;
3880 KLoc[Modifier2] = Tok.getLocation();
3881 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3882 Tok.isNot(K: tok::annot_pragma_openmp_end))
3883 ConsumeAnyToken();
3884 }
3885 // Parse ':'
3886 if (Tok.is(K: tok::colon))
3887 ConsumeAnyToken();
3888 else
3889 Diag(Tok, DiagID: diag::warn_pragma_expected_colon) << "schedule modifier";
3890 KindModifier = getOpenMPSimpleClauseType(
3891 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
3892 }
3893 Arg[ScheduleKind] = KindModifier;
3894 KLoc[ScheduleKind] = Tok.getLocation();
3895 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3896 Tok.isNot(K: tok::annot_pragma_openmp_end))
3897 ConsumeAnyToken();
3898 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3899 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3900 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3901 Tok.is(K: tok::comma))
3902 DelimLoc = ConsumeAnyToken();
3903 } else if (Kind == OMPC_dist_schedule) {
3904 Arg.push_back(Elt: getOpenMPSimpleClauseType(
3905 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts()));
3906 KLoc.push_back(Elt: Tok.getLocation());
3907 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3908 Tok.isNot(K: tok::annot_pragma_openmp_end))
3909 ConsumeAnyToken();
3910 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(K: tok::comma))
3911 DelimLoc = ConsumeAnyToken();
3912 } else if (Kind == OMPC_default) {
3913 // Get a default modifier
3914 unsigned Modifier = getOpenMPSimpleClauseType(
3915 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
3916
3917 Arg.push_back(Elt: Modifier);
3918 KLoc.push_back(Elt: Tok.getLocation());
3919 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3920 Tok.isNot(K: tok::annot_pragma_openmp_end))
3921 ConsumeAnyToken();
3922 // Parse ':'
3923 if (Tok.is(K: tok::colon) && getLangOpts().OpenMP >= 60) {
3924 ConsumeAnyToken();
3925 // Get a variable-category attribute for default clause modifier
3926 OpenMPDefaultClauseVariableCategory VariableCategory =
3927 getOpenMPDefaultVariableCategory(
3928 Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
3929 Arg.push_back(Elt: VariableCategory);
3930 KLoc.push_back(Elt: Tok.getLocation());
3931 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3932 Tok.isNot(K: tok::annot_pragma_openmp_end))
3933 ConsumeAnyToken();
3934 } else {
3935 Arg.push_back(Elt: OMPC_DEFAULT_VC_all);
3936 KLoc.push_back(Elt: SourceLocation());
3937 }
3938 } else if (Kind == OMPC_defaultmap) {
3939 // Get a defaultmap modifier
3940 unsigned Modifier = getOpenMPSimpleClauseType(
3941 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
3942
3943 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
3944 // pointer
3945 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
3946 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
3947 Arg.push_back(Elt: Modifier);
3948 KLoc.push_back(Elt: Tok.getLocation());
3949 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3950 Tok.isNot(K: tok::annot_pragma_openmp_end))
3951 ConsumeAnyToken();
3952 // Parse ':'
3953 if (Tok.is(K: tok::colon) || getLangOpts().OpenMP < 50) {
3954 if (Tok.is(K: tok::colon))
3955 ConsumeAnyToken();
3956 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
3957 Diag(Tok, DiagID: diag::warn_pragma_expected_colon) << "defaultmap modifier";
3958 // Get a defaultmap kind
3959 Arg.push_back(Elt: getOpenMPSimpleClauseType(
3960 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts()));
3961 KLoc.push_back(Elt: Tok.getLocation());
3962 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3963 Tok.isNot(K: tok::annot_pragma_openmp_end))
3964 ConsumeAnyToken();
3965 } else {
3966 Arg.push_back(Elt: OMPC_DEFAULTMAP_unknown);
3967 KLoc.push_back(Elt: SourceLocation());
3968 }
3969 } else if (Kind == OMPC_order) {
3970 enum { Modifier, OrderKind, NumberOfElements };
3971 Arg.resize(N: NumberOfElements);
3972 KLoc.resize(N: NumberOfElements);
3973 Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
3974 Arg[OrderKind] = OMPC_ORDER_unknown;
3975 unsigned KindModifier = getOpenMPSimpleClauseType(
3976 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
3977 if (KindModifier > OMPC_ORDER_unknown) {
3978 // Parse 'modifier'
3979 Arg[Modifier] = KindModifier;
3980 KLoc[Modifier] = Tok.getLocation();
3981 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3982 Tok.isNot(K: tok::annot_pragma_openmp_end))
3983 ConsumeAnyToken();
3984 // Parse ':'
3985 if (Tok.is(K: tok::colon))
3986 ConsumeAnyToken();
3987 else
3988 Diag(Tok, DiagID: diag::warn_pragma_expected_colon) << "order modifier";
3989 KindModifier = getOpenMPSimpleClauseType(
3990 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
3991 }
3992 Arg[OrderKind] = KindModifier;
3993 KLoc[OrderKind] = Tok.getLocation();
3994 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
3995 Tok.isNot(K: tok::annot_pragma_openmp_end))
3996 ConsumeAnyToken();
3997 } else if (Kind == OMPC_device) {
3998 // Only target executable directives support extended device construct.
3999 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4000 NextToken().is(K: tok::colon)) {
4001 // Parse optional <device modifier> ':'
4002 Arg.push_back(Elt: getOpenMPSimpleClauseType(
4003 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts()));
4004 KLoc.push_back(Elt: Tok.getLocation());
4005 ConsumeAnyToken();
4006 // Parse ':'
4007 ConsumeAnyToken();
4008 } else {
4009 Arg.push_back(Elt: OMPC_DEVICE_unknown);
4010 KLoc.emplace_back();
4011 }
4012 } else if (Kind == OMPC_grainsize) {
4013 // Parse optional <grainsize modifier> ':'
4014 OpenMPGrainsizeClauseModifier Modifier =
4015 static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType(
4016 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4017 LangOpts: getLangOpts()));
4018 if (getLangOpts().OpenMP >= 51) {
4019 if (NextToken().is(K: tok::colon)) {
4020 Arg.push_back(Elt: Modifier);
4021 KLoc.push_back(Elt: Tok.getLocation());
4022 // Parse modifier
4023 ConsumeAnyToken();
4024 // Parse ':'
4025 ConsumeAnyToken();
4026 } else {
4027 if (Modifier == OMPC_GRAINSIZE_strict) {
4028 Diag(Tok, DiagID: diag::err_modifier_expected_colon) << "strict";
4029 // Parse modifier
4030 ConsumeAnyToken();
4031 }
4032 Arg.push_back(Elt: OMPC_GRAINSIZE_unknown);
4033 KLoc.emplace_back();
4034 }
4035 } else {
4036 Arg.push_back(Elt: OMPC_GRAINSIZE_unknown);
4037 KLoc.emplace_back();
4038 }
4039 } else if (Kind == OMPC_dyn_groupprivate) {
4040 enum { SimpleModifier, ComplexModifier, NumberOfModifiers };
4041 Arg.resize(N: NumberOfModifiers);
4042 KLoc.resize(N: NumberOfModifiers);
4043 Arg[SimpleModifier] = OMPC_DYN_GROUPPRIVATE_unknown;
4044 Arg[ComplexModifier] = OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown;
4045
4046 auto ConsumeModifier = [&]() {
4047 unsigned Type = NumberOfModifiers;
4048 unsigned Modifier;
4049 SourceLocation Loc;
4050 if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&
4051 NextToken().is(K: tok::l_paren)) {
4052 ConsumeToken();
4053 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4054 ParenT.consumeOpen();
4055
4056 Modifier = getOpenMPSimpleClauseType(
4057 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
4058 if (Modifier <= OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown ||
4059 Modifier >= OMPC_DYN_GROUPPRIVATE_FALLBACK_last) {
4060 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected)
4061 << "'abort', 'null' or 'default_mem' in fallback modifier";
4062 SkipUntil(T: tok::r_paren);
4063 return std::make_tuple(args&: Type, args&: Modifier, args&: Loc);
4064 }
4065 Type = ComplexModifier;
4066 Loc = Tok.getLocation();
4067 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
4068 Tok.isNot(K: tok::annot_pragma_openmp_end))
4069 ConsumeAnyToken();
4070 ParenT.consumeClose();
4071 } else {
4072 Modifier = getOpenMPSimpleClauseType(
4073 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok), LangOpts: getLangOpts());
4074 if (Modifier < OMPC_DYN_GROUPPRIVATE_unknown) {
4075 Type = SimpleModifier;
4076 Loc = Tok.getLocation();
4077 if (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::comma) &&
4078 Tok.isNot(K: tok::annot_pragma_openmp_end))
4079 ConsumeAnyToken();
4080 }
4081 }
4082 return std::make_tuple(args&: Type, args&: Modifier, args&: Loc);
4083 };
4084
4085 auto SaveModifier = [&](unsigned Type, unsigned Modifier,
4086 SourceLocation Loc) {
4087 assert(Type < NumberOfModifiers && "Unexpected modifier type");
4088 if (!KLoc[Type].isValid()) {
4089 Arg[Type] = Modifier;
4090 KLoc[Type] = Loc;
4091 } else {
4092 Diag(Loc, DiagID: diag::err_omp_incompatible_dyn_groupprivate_modifier)
4093 << getOpenMPSimpleClauseTypeName(Kind: OMPC_dyn_groupprivate, Type: Modifier)
4094 << getOpenMPSimpleClauseTypeName(Kind: OMPC_dyn_groupprivate, Type: Arg[Type]);
4095 }
4096 };
4097
4098 // Parse 'modifier'
4099 auto [Type1, Mod1, Loc1] = ConsumeModifier();
4100 if (Type1 < NumberOfModifiers) {
4101 SaveModifier(Type1, Mod1, Loc1);
4102 if (Tok.is(K: tok::comma)) {
4103 // Parse ',' 'modifier'
4104 ConsumeAnyToken();
4105 auto [Type2, Mod2, Loc2] = ConsumeModifier();
4106 if (Type2 < NumberOfModifiers)
4107 SaveModifier(Type2, Mod2, Loc2);
4108 }
4109 // Parse ':'
4110 if (Tok.is(K: tok::colon))
4111 ConsumeAnyToken();
4112 else
4113 Diag(Tok, DiagID: diag::warn_pragma_expected_colon)
4114 << "dyn_groupprivate modifier";
4115 }
4116 } else if (Kind == OMPC_num_tasks) {
4117 // Parse optional <num_tasks modifier> ':'
4118 OpenMPNumTasksClauseModifier Modifier =
4119 static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(
4120 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4121 LangOpts: getLangOpts()));
4122 if (getLangOpts().OpenMP >= 51) {
4123 if (NextToken().is(K: tok::colon)) {
4124 Arg.push_back(Elt: Modifier);
4125 KLoc.push_back(Elt: Tok.getLocation());
4126 // Parse modifier
4127 ConsumeAnyToken();
4128 // Parse ':'
4129 ConsumeAnyToken();
4130 } else {
4131 if (Modifier == OMPC_NUMTASKS_strict) {
4132 Diag(Tok, DiagID: diag::err_modifier_expected_colon) << "strict";
4133 // Parse modifier
4134 ConsumeAnyToken();
4135 }
4136 Arg.push_back(Elt: OMPC_NUMTASKS_unknown);
4137 KLoc.emplace_back();
4138 }
4139 } else {
4140 Arg.push_back(Elt: OMPC_NUMTASKS_unknown);
4141 KLoc.emplace_back();
4142 }
4143 } else if (Kind == OMPC_num_threads) {
4144 // Parse optional <num_threads modifier> ':'
4145 OpenMPNumThreadsClauseModifier Modifier =
4146 static_cast<OpenMPNumThreadsClauseModifier>(getOpenMPSimpleClauseType(
4147 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4148 LangOpts: getLangOpts()));
4149 if (getLangOpts().OpenMP >= 60) {
4150 if (NextToken().is(K: tok::colon)) {
4151 Arg.push_back(Elt: Modifier);
4152 KLoc.push_back(Elt: Tok.getLocation());
4153 // Parse modifier
4154 ConsumeAnyToken();
4155 // Parse ':'
4156 ConsumeAnyToken();
4157 } else {
4158 if (Modifier == OMPC_NUMTHREADS_strict) {
4159 Diag(Tok, DiagID: diag::err_modifier_expected_colon) << "strict";
4160 // Parse modifier
4161 ConsumeAnyToken();
4162 }
4163 Arg.push_back(Elt: OMPC_NUMTHREADS_unknown);
4164 KLoc.emplace_back();
4165 }
4166 } else {
4167 Arg.push_back(Elt: OMPC_NUMTHREADS_unknown);
4168 KLoc.emplace_back();
4169 }
4170 } else {
4171 assert(Kind == OMPC_if);
4172 KLoc.push_back(Elt: Tok.getLocation());
4173 TentativeParsingAction TPA(*this);
4174 auto DK = parseOpenMPDirectiveKind(P&: *this);
4175 Arg.push_back(Elt: static_cast<unsigned>(DK));
4176 if (DK != OMPD_unknown) {
4177 ConsumeToken();
4178 if (Tok.is(K: tok::colon) && getLangOpts().OpenMP > 40) {
4179 TPA.Commit();
4180 DelimLoc = ConsumeToken();
4181 } else {
4182 TPA.Revert();
4183 Arg.back() = unsigned(OMPD_unknown);
4184 }
4185 } else {
4186 TPA.Revert();
4187 }
4188 }
4189
4190 bool NeedAnExpression =
4191 (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4192 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||
4193 Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||
4194 Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;
4195 if (NeedAnExpression) {
4196 SourceLocation ELoc = Tok.getLocation();
4197 ExprResult LHS(
4198 ParseCastExpression(ParseKind: CastParseKind::AnyCastExpr, isAddressOfOperand: false,
4199 CorrectionBehavior: TypoCorrectionTypeBehavior::AllowNonTypes));
4200 Val = ParseRHSOfBinaryExpression(LHS, MinPrec: prec::Conditional);
4201 Val =
4202 Actions.ActOnFinishFullExpr(Expr: Val.get(), CC: ELoc, /*DiscardedValue*/ false);
4203 }
4204
4205 // Parse ')'.
4206 SourceLocation RLoc = Tok.getLocation();
4207 if (!T.consumeClose())
4208 RLoc = T.getCloseLocation();
4209
4210 if (NeedAnExpression && Val.isInvalid())
4211 return nullptr;
4212
4213 if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&
4214 (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||
4215 static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {
4216 Diag(Loc: KLoc[0], DiagID: diag::err_omp_invalid_dsa)
4217 << getOpenMPClauseName(C: static_cast<DefaultKind>(Arg[0]) ==
4218 OMP_DEFAULT_private
4219 ? OMPC_private
4220 : OMPC_firstprivate)
4221 << getOpenMPClauseName(C: OMPC_default) << "5.1";
4222 return nullptr;
4223 }
4224
4225 if (ParseOnly)
4226 return nullptr;
4227 return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4228 Kind, Arguments: Arg, Expr: Val.get(), StartLoc: Loc, LParenLoc: T.getOpenLocation(), ArgumentsLoc: KLoc, DelimLoc, EndLoc: RLoc);
4229}
4230
4231static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4232 UnqualifiedId &ReductionId) {
4233 if (ReductionIdScopeSpec.isEmpty()) {
4234 auto OOK = OO_None;
4235 switch (P.getCurToken().getKind()) {
4236 case tok::plus:
4237 OOK = OO_Plus;
4238 break;
4239 case tok::minus:
4240 OOK = OO_Minus;
4241 break;
4242 case tok::star:
4243 OOK = OO_Star;
4244 break;
4245 case tok::amp:
4246 OOK = OO_Amp;
4247 break;
4248 case tok::pipe:
4249 OOK = OO_Pipe;
4250 break;
4251 case tok::caret:
4252 OOK = OO_Caret;
4253 break;
4254 case tok::ampamp:
4255 OOK = OO_AmpAmp;
4256 break;
4257 case tok::pipepipe:
4258 OOK = OO_PipePipe;
4259 break;
4260 default:
4261 break;
4262 }
4263 if (OOK != OO_None) {
4264 SourceLocation OpLoc = P.ConsumeToken();
4265 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4266 ReductionId.setOperatorFunctionId(OperatorLoc: OpLoc, Op: OOK, SymbolLocations);
4267 return false;
4268 }
4269 }
4270 return P.ParseUnqualifiedId(
4271 SS&: ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4272 /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4273 /*AllowDestructorName*/ false,
4274 /*AllowConstructorName*/ false,
4275 /*AllowDeductionGuide*/ false, TemplateKWLoc: nullptr, Result&: ReductionId);
4276}
4277
4278/// Checks if the token is a valid map-type-modifier.
4279/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4280static OpenMPMapModifierKind isMapModifier(Parser &P) {
4281 Token Tok = P.getCurToken();
4282 if (!Tok.is(K: tok::identifier))
4283 return OMPC_MAP_MODIFIER_unknown;
4284
4285 Preprocessor &PP = P.getPreprocessor();
4286 OpenMPMapModifierKind TypeModifier =
4287 static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(
4288 Kind: OMPC_map, Str: PP.getSpelling(Tok), LangOpts: P.getLangOpts()));
4289 return TypeModifier;
4290}
4291
4292bool Parser::parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data) {
4293 // Parse '('.
4294 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4295 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after, Msg: "mapper")) {
4296 SkipUntil(T1: tok::colon, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
4297 Flags: StopBeforeMatch);
4298 return true;
4299 }
4300 // Parse mapper-identifier
4301 if (getLangOpts().CPlusPlus)
4302 ParseOptionalCXXScopeSpecifier(SS&: Data.ReductionOrMapperIdScopeSpec,
4303 /*ObjectType=*/nullptr,
4304 /*ObjectHasErrors=*/false,
4305 /*EnteringContext=*/false);
4306 if (Tok.isNot(K: tok::identifier) && Tok.isNot(K: tok::kw_default)) {
4307 Diag(Loc: Tok.getLocation(), DiagID: diag::err_omp_mapper_illegal_identifier);
4308 SkipUntil(T1: tok::colon, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
4309 Flags: StopBeforeMatch);
4310 return true;
4311 }
4312 auto &DeclNames = Actions.getASTContext().DeclarationNames;
4313 Data.ReductionOrMapperId = DeclarationNameInfo(
4314 DeclNames.getIdentifier(ID: Tok.getIdentifierInfo()), Tok.getLocation());
4315 ConsumeToken();
4316 // Parse ')'.
4317 return T.consumeClose();
4318}
4319
4320static OpenMPMapClauseKind isMapType(Parser &P);
4321
4322bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) {
4323 bool HasMapType = false;
4324 SourceLocation PreMapLoc = Tok.getLocation();
4325 StringRef PreMapName = "";
4326 while (getCurToken().isNot(K: tok::colon)) {
4327 OpenMPMapModifierKind TypeModifier = isMapModifier(P&: *this);
4328 OpenMPMapClauseKind MapKind = isMapType(P&: *this);
4329 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4330 TypeModifier == OMPC_MAP_MODIFIER_close ||
4331 TypeModifier == OMPC_MAP_MODIFIER_present ||
4332 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4333 Data.MapTypeModifiers.push_back(Elt: TypeModifier);
4334 Data.MapTypeModifiersLoc.push_back(Elt: Tok.getLocation());
4335 if (PP.LookAhead(N: 0).isNot(K: tok::comma) &&
4336 PP.LookAhead(N: 0).isNot(K: tok::colon) && getLangOpts().OpenMP >= 52)
4337 Diag(Loc: Tok.getLocation(), DiagID: diag::err_omp_missing_comma)
4338 << "map type modifier";
4339 ConsumeToken();
4340 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4341 Data.MapTypeModifiers.push_back(Elt: TypeModifier);
4342 Data.MapTypeModifiersLoc.push_back(Elt: Tok.getLocation());
4343 ConsumeToken();
4344 if (parseMapperModifier(Data))
4345 return true;
4346 if (Tok.isNot(K: tok::comma) && Tok.isNot(K: tok::colon) &&
4347 getLangOpts().OpenMP >= 52)
4348 Diag(Loc: Data.MapTypeModifiersLoc.back(), DiagID: diag::err_omp_missing_comma)
4349 << "map type modifier";
4350
4351 } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4352 if (!HasMapType) {
4353 HasMapType = true;
4354 Data.ExtraModifier = MapKind;
4355 MapKind = OMPC_MAP_unknown;
4356 PreMapLoc = Tok.getLocation();
4357 PreMapName = Tok.getIdentifierInfo()->getName();
4358 } else {
4359 Diag(Tok, DiagID: diag::err_omp_more_one_map_type);
4360 Diag(Loc: PreMapLoc, DiagID: diag::note_previous_map_type_specified_here)
4361 << PreMapName;
4362 }
4363 ConsumeToken();
4364 } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {
4365 Data.MapTypeModifiers.push_back(Elt: TypeModifier);
4366 Data.MapTypeModifiersLoc.push_back(Elt: Tok.getLocation());
4367 if (PP.LookAhead(N: 0).isNot(K: tok::comma) &&
4368 PP.LookAhead(N: 0).isNot(K: tok::colon))
4369 Diag(Loc: Tok.getLocation(), DiagID: diag::err_omp_missing_comma)
4370 << "map type modifier";
4371 if (getLangOpts().OpenMP < 60)
4372 Diag(Tok, DiagID: diag::err_omp_unknown_map_type_modifier)
4373 << (getLangOpts().OpenMP >= 51
4374 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4375 : 0)
4376 << getLangOpts().OpenMPExtensions << 0;
4377 ConsumeToken();
4378 } else {
4379 // For the case of unknown map-type-modifier or a map-type.
4380 // Map-type is followed by a colon; the function returns when it
4381 // encounters a token followed by a colon.
4382 if (Tok.is(K: tok::comma)) {
4383 Diag(Tok, DiagID: diag::err_omp_map_type_modifier_missing);
4384 ConsumeToken();
4385 continue;
4386 }
4387 // Potential map-type token as it is followed by a colon.
4388 if (PP.LookAhead(N: 0).is(K: tok::colon)) {
4389 if (getLangOpts().OpenMP >= 60) {
4390 break;
4391 } else {
4392 return false;
4393 }
4394 }
4395
4396 Diag(Tok, DiagID: diag::err_omp_unknown_map_type_modifier)
4397 << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4398 : 0)
4399 << getLangOpts().OpenMPExtensions
4400 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
4401 ConsumeToken();
4402 }
4403 if (getCurToken().is(K: tok::comma))
4404 ConsumeToken();
4405 }
4406 if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4407 if (!Tok.is(K: tok::colon)) {
4408 Diag(Tok, DiagID: diag::err_omp_unknown_map_type);
4409 ConsumeToken();
4410 } else {
4411 Data.ExtraModifier = OMPC_MAP_unknown;
4412 }
4413 }
4414 return false;
4415}
4416
4417/// Checks if the token is a valid map-type.
4418/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4419static OpenMPMapClauseKind isMapType(Parser &P) {
4420 Token Tok = P.getCurToken();
4421 // The map-type token can be either an identifier or the C++ delete keyword.
4422 if (!Tok.isOneOf(Ks: tok::identifier, Ks: tok::kw_delete))
4423 return OMPC_MAP_unknown;
4424 Preprocessor &PP = P.getPreprocessor();
4425 unsigned MapType =
4426 getOpenMPSimpleClauseType(Kind: OMPC_map, Str: PP.getSpelling(Tok), LangOpts: P.getLangOpts());
4427 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4428 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4429 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4430 return static_cast<OpenMPMapClauseKind>(MapType);
4431 return OMPC_MAP_unknown;
4432}
4433
4434/// Parse map-type in map clause.
4435/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4436/// where, map-type ::= to | from | tofrom | alloc | release | delete
4437static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data) {
4438 Token Tok = P.getCurToken();
4439 if (Tok.is(K: tok::colon)) {
4440 P.Diag(Tok, DiagID: diag::err_omp_map_type_missing);
4441 return;
4442 }
4443 Data.ExtraModifier = isMapType(P);
4444 if (Data.ExtraModifier == OMPC_MAP_unknown)
4445 P.Diag(Tok, DiagID: diag::err_omp_unknown_map_type);
4446 P.ConsumeToken();
4447}
4448
4449ExprResult Parser::ParseOpenMPIteratorsExpr() {
4450 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4451 "Expected 'iterator' token.");
4452 SourceLocation IteratorKwLoc = ConsumeToken();
4453
4454 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4455 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after, Msg: "iterator"))
4456 return ExprError();
4457
4458 SourceLocation LLoc = T.getOpenLocation();
4459 SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
4460 while (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::annot_pragma_openmp_end)) {
4461 // Check if the type parsing is required.
4462 ParsedType IteratorType;
4463 if (Tok.isNot(K: tok::identifier) || NextToken().isNot(K: tok::equal)) {
4464 // identifier '=' is not found - parse type.
4465 TypeResult TR = ParseTypeName();
4466 if (TR.isInvalid()) {
4467 T.skipToEnd();
4468 return ExprError();
4469 }
4470 IteratorType = TR.get();
4471 }
4472
4473 // Parse identifier.
4474 IdentifierInfo *II = nullptr;
4475 SourceLocation IdLoc;
4476 if (Tok.is(K: tok::identifier)) {
4477 II = Tok.getIdentifierInfo();
4478 IdLoc = ConsumeToken();
4479 } else {
4480 Diag(Tok, DiagID: diag::err_expected_unqualified_id) << 0;
4481 }
4482
4483 // Parse '='.
4484 SourceLocation AssignLoc;
4485 if (Tok.is(K: tok::equal))
4486 AssignLoc = ConsumeToken();
4487 else
4488 Diag(Tok, DiagID: diag::err_omp_expected_equal_in_iterator);
4489
4490 // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4491 ColonProtectionRAIIObject ColonRAII(*this);
4492 // Parse <begin>
4493 SourceLocation Loc = Tok.getLocation();
4494 ExprResult LHS = ParseCastExpression(ParseKind: CastParseKind::AnyCastExpr);
4495 ExprResult Begin = ParseRHSOfBinaryExpression(LHS, MinPrec: prec::Conditional);
4496 Begin = Actions.ActOnFinishFullExpr(Expr: Begin.get(), CC: Loc,
4497 /*DiscardedValue=*/false);
4498 // Parse ':'.
4499 SourceLocation ColonLoc;
4500 if (Tok.is(K: tok::colon))
4501 ColonLoc = ConsumeToken();
4502
4503 // Parse <end>
4504 Loc = Tok.getLocation();
4505 LHS = ParseCastExpression(ParseKind: CastParseKind::AnyCastExpr);
4506 ExprResult End = ParseRHSOfBinaryExpression(LHS, MinPrec: prec::Conditional);
4507 End = Actions.ActOnFinishFullExpr(Expr: End.get(), CC: Loc,
4508 /*DiscardedValue=*/false);
4509
4510 SourceLocation SecColonLoc;
4511 ExprResult Step;
4512 // Parse optional step.
4513 if (Tok.is(K: tok::colon)) {
4514 // Parse ':'
4515 SecColonLoc = ConsumeToken();
4516 // Parse <step>
4517 Loc = Tok.getLocation();
4518 LHS = ParseCastExpression(ParseKind: CastParseKind::AnyCastExpr);
4519 Step = ParseRHSOfBinaryExpression(LHS, MinPrec: prec::Conditional);
4520 Step = Actions.ActOnFinishFullExpr(Expr: Step.get(), CC: Loc,
4521 /*DiscardedValue=*/false);
4522 }
4523
4524 // Parse ',' or ')'
4525 if (Tok.isNot(K: tok::comma) && Tok.isNot(K: tok::r_paren))
4526 Diag(Tok, DiagID: diag::err_omp_expected_punc_after_iterator);
4527 if (Tok.is(K: tok::comma))
4528 ConsumeToken();
4529
4530 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4531 D.DeclIdent = II;
4532 D.DeclIdentLoc = IdLoc;
4533 D.Type = IteratorType;
4534 D.AssignLoc = AssignLoc;
4535 D.ColonLoc = ColonLoc;
4536 D.SecColonLoc = SecColonLoc;
4537 D.Range.Begin = Begin.get();
4538 D.Range.End = End.get();
4539 D.Range.Step = Step.get();
4540 }
4541
4542 // Parse ')'.
4543 SourceLocation RLoc = Tok.getLocation();
4544 if (!T.consumeClose())
4545 RLoc = T.getCloseLocation();
4546
4547 return Actions.OpenMP().ActOnOMPIteratorExpr(S: getCurScope(), IteratorKwLoc,
4548 LLoc, RLoc, Data);
4549}
4550
4551bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind,
4552 SemaOpenMP::OpenMPVarListDataTy &Data,
4553 const LangOptions &LangOpts) {
4554 // Currently the only reserved locator is 'omp_all_memory' which is only
4555 // allowed on a depend clause.
4556 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4557 return false;
4558
4559 if (Tok.is(K: tok::identifier) &&
4560 Tok.getIdentifierInfo()->isStr(Str: "omp_all_memory")) {
4561
4562 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4563 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4564 Diag(Tok, DiagID: diag::warn_omp_more_one_omp_all_memory);
4565 else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4566 Data.ExtraModifier != OMPC_DEPEND_inout)
4567 Diag(Tok, DiagID: diag::err_omp_requires_out_inout_depend_type);
4568 else
4569 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4570 ? OMPC_DEPEND_outallmemory
4571 : OMPC_DEPEND_inoutallmemory;
4572 ConsumeToken();
4573 return true;
4574 }
4575 return false;
4576}
4577
4578/// Parse step size expression. Returns true if parsing is successfull,
4579/// otherwise returns false.
4580static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data,
4581 OpenMPClauseKind CKind, SourceLocation ELoc) {
4582 ExprResult Tail = P.ParseAssignmentExpression();
4583 Sema &Actions = P.getActions();
4584 Tail = Actions.ActOnFinishFullExpr(Expr: Tail.get(), CC: ELoc,
4585 /*DiscardedValue*/ false);
4586 if (Tail.isUsable()) {
4587 Data.DepModOrTailExpr = Tail.get();
4588 Token CurTok = P.getCurToken();
4589 if (CurTok.isNot(K: tok::r_paren) && CurTok.isNot(K: tok::comma)) {
4590 P.Diag(Tok: CurTok, DiagID: diag::err_expected_punc) << "step expression";
4591 }
4592 return true;
4593 }
4594 return false;
4595}
4596
4597/// Parse 'allocate' clause modifiers.
4598/// If allocator-modifier exists, return an expression for it. For both
4599/// allocator and align modifiers, set Data fields as appropriate.
4600static ExprResult
4601parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind,
4602 SemaOpenMP::OpenMPVarListDataTy &Data) {
4603 const Token &Tok = P.getCurToken();
4604 Preprocessor &PP = P.getPreprocessor();
4605 ExprResult Tail;
4606 ExprResult Val;
4607 SourceLocation RLoc;
4608 bool AllocatorSeen = false;
4609 bool AlignSeen = false;
4610 SourceLocation CurrentModifierLoc = Tok.getLocation();
4611 auto CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4612 getOpenMPSimpleClauseType(Kind, Str: PP.getSpelling(Tok), LangOpts: P.getLangOpts()));
4613
4614 // Modifiers did not exist before 5.1
4615 if (P.getLangOpts().OpenMP < 51)
4616 return P.ParseAssignmentExpression();
4617
4618 // An allocator-simple-modifier is exclusive and must appear alone. See
4619 // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
4620 // description of "exclusive" property. If we don't recognized an explicit
4621 // simple-/complex- modifier, assume we're looking at expression
4622 // representing allocator and consider ourselves done.
4623 if (CurrentModifier == OMPC_ALLOCATE_unknown)
4624 return P.ParseAssignmentExpression();
4625
4626 do {
4627 P.ConsumeToken();
4628 if (Tok.is(K: tok::l_paren)) {
4629 switch (CurrentModifier) {
4630 case OMPC_ALLOCATE_allocator: {
4631 if (AllocatorSeen) {
4632 P.Diag(Tok, DiagID: diag::err_omp_duplicate_modifier)
4633 << getOpenMPSimpleClauseTypeName(Kind: OMPC_allocate, Type: CurrentModifier)
4634 << getOpenMPClauseName(C: Kind);
4635 } else {
4636 Data.AllocClauseModifiers.push_back(Elt: CurrentModifier);
4637 Data.AllocClauseModifiersLoc.push_back(Elt: CurrentModifierLoc);
4638 }
4639 BalancedDelimiterTracker AllocateT(P, tok::l_paren,
4640 tok::annot_pragma_openmp_end);
4641 AllocateT.consumeOpen();
4642 Tail = P.ParseAssignmentExpression();
4643 AllocateT.consumeClose();
4644 AllocatorSeen = true;
4645 break;
4646 }
4647 case OMPC_ALLOCATE_align: {
4648 if (AlignSeen) {
4649 P.Diag(Tok, DiagID: diag::err_omp_duplicate_modifier)
4650 << getOpenMPSimpleClauseTypeName(Kind: OMPC_allocate, Type: CurrentModifier)
4651 << getOpenMPClauseName(C: Kind);
4652 } else {
4653 Data.AllocClauseModifiers.push_back(Elt: CurrentModifier);
4654 Data.AllocClauseModifiersLoc.push_back(Elt: CurrentModifierLoc);
4655 }
4656 Val = P.ParseOpenMPParensExpr(ClauseName: getOpenMPClauseName(C: Kind), RLoc);
4657 if (Val.isUsable())
4658 Data.AllocateAlignment = Val.get();
4659 AlignSeen = true;
4660 break;
4661 }
4662 default:
4663 llvm_unreachable("Unexpected allocate modifier");
4664 }
4665 } else {
4666 P.Diag(Tok, DiagID: diag::err_expected) << tok::l_paren;
4667 }
4668 if (Tok.isNot(K: tok::comma))
4669 break;
4670 P.ConsumeToken();
4671 CurrentModifierLoc = Tok.getLocation();
4672 CurrentModifier = static_cast<OpenMPAllocateClauseModifier>(
4673 getOpenMPSimpleClauseType(Kind, Str: PP.getSpelling(Tok), LangOpts: P.getLangOpts()));
4674 // A modifier followed by a comma implies another modifier.
4675 if (CurrentModifier == OMPC_ALLOCATE_unknown) {
4676 P.Diag(Tok, DiagID: diag::err_omp_expected_modifier) << getOpenMPClauseName(C: Kind);
4677 break;
4678 }
4679 } while (!AllocatorSeen || !AlignSeen);
4680 return Tail;
4681}
4682
4683bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
4684 OpenMPClauseKind Kind,
4685 SmallVectorImpl<Expr *> &Vars,
4686 SemaOpenMP::OpenMPVarListDataTy &Data) {
4687 UnqualifiedId UnqualifiedReductionId;
4688 bool InvalidReductionId = false;
4689 bool IsInvalidMapperModifier = false;
4690
4691 // Parse '('.
4692 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4693 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after,
4694 Msg: getOpenMPClauseName(C: Kind).data()))
4695 return true;
4696
4697 bool HasIterator = false;
4698 bool InvalidIterator = false;
4699 bool NeedRParenForLinear = false;
4700 BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4701 tok::annot_pragma_openmp_end);
4702 // Handle reduction-identifier for reduction clause.
4703 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4704 Kind == OMPC_in_reduction) {
4705 Data.ExtraModifier = OMPC_REDUCTION_unknown;
4706 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4707 (Tok.is(K: tok::identifier) || Tok.is(K: tok::kw_default)) &&
4708 NextToken().is(K: tok::comma)) {
4709 // Parse optional reduction modifier.
4710 Data.ExtraModifier =
4711 getOpenMPSimpleClauseType(Kind, Str: PP.getSpelling(Tok), LangOpts: getLangOpts());
4712 Data.ExtraModifierLoc = Tok.getLocation();
4713 ConsumeToken();
4714 assert(Tok.is(tok::comma) && "Expected comma.");
4715 (void)ConsumeToken();
4716 }
4717 // Handle original(private / shared) Modifier
4718 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
4719 Tok.is(K: tok::identifier) && PP.getSpelling(Tok) == "original" &&
4720 NextToken().is(K: tok::l_paren)) {
4721 // Parse original(private) modifier.
4722 ConsumeToken();
4723 BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
4724 ParenT.consumeOpen();
4725 if (Tok.is(K: tok::kw_private)) {
4726 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
4727 Data.OriginalSharingModifierLoc = Tok.getLocation();
4728 ConsumeToken();
4729 } else if (Tok.is(K: tok::identifier) &&
4730 (PP.getSpelling(Tok) == "shared" ||
4731 PP.getSpelling(Tok) == "default")) {
4732 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
4733 Data.OriginalSharingModifierLoc = Tok.getLocation();
4734 ConsumeToken();
4735 } else {
4736 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected)
4737 << "'private or shared or default'";
4738 SkipUntil(T: tok::r_paren);
4739 return false;
4740 }
4741 ParenT.consumeClose();
4742 if (!Tok.is(K: tok::comma)) {
4743 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected) << "',' (comma)";
4744 return false;
4745 }
4746 (void)ConsumeToken();
4747 }
4748 ColonProtectionRAIIObject ColonRAII(*this);
4749 if (getLangOpts().CPlusPlus)
4750 ParseOptionalCXXScopeSpecifier(SS&: Data.ReductionOrMapperIdScopeSpec,
4751 /*ObjectType=*/nullptr,
4752 /*ObjectHasErrors=*/false,
4753 /*EnteringContext=*/false);
4754 InvalidReductionId = ParseReductionId(
4755 P&: *this, ReductionIdScopeSpec&: Data.ReductionOrMapperIdScopeSpec, ReductionId&: UnqualifiedReductionId);
4756 if (InvalidReductionId) {
4757 SkipUntil(T1: tok::colon, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
4758 Flags: StopBeforeMatch);
4759 }
4760 if (Tok.is(K: tok::colon))
4761 Data.ColonLoc = ConsumeToken();
4762 else
4763 Diag(Tok, DiagID: diag::warn_pragma_expected_colon) << "reduction identifier";
4764 if (!InvalidReductionId)
4765 Data.ReductionOrMapperId =
4766 Actions.GetNameFromUnqualifiedId(Name: UnqualifiedReductionId);
4767 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4768 if (getLangOpts().OpenMP >= 50) {
4769 if (Tok.is(K: tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4770 // Handle optional dependence modifier.
4771 // iterator(iterators-definition)
4772 // where iterators-definition is iterator-specifier [,
4773 // iterators-definition ]
4774 // where iterator-specifier is [ iterator-type ] identifier =
4775 // range-specification
4776 HasIterator = true;
4777 EnterScope(ScopeFlags: Scope::OpenMPDirectiveScope | Scope::DeclScope);
4778 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4779 Data.DepModOrTailExpr = IteratorRes.get();
4780 // Parse ','
4781 ExpectAndConsume(ExpectedTok: tok::comma);
4782 }
4783 }
4784 // Handle dependency type for depend clause.
4785 ColonProtectionRAIIObject ColonRAII(*this);
4786 Data.ExtraModifier = getOpenMPSimpleClauseType(
4787 Kind, Str: Tok.is(K: tok::identifier) ? PP.getSpelling(Tok) : "",
4788 LangOpts: getLangOpts());
4789 Data.ExtraModifierLoc = Tok.getLocation();
4790 if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
4791 (Kind == OMPC_doacross &&
4792 Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
4793 SkipUntil(T1: tok::colon, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
4794 Flags: StopBeforeMatch);
4795 } else {
4796 ConsumeToken();
4797 // Special processing for depend(source) clause.
4798 if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4799 Data.ExtraModifier == OMPC_DEPEND_source) {
4800 // Parse ')'.
4801 T.consumeClose();
4802 return false;
4803 }
4804 }
4805 if (Tok.is(K: tok::colon)) {
4806 Data.ColonLoc = ConsumeToken();
4807 } else if (Kind != OMPC_doacross || Tok.isNot(K: tok::r_paren)) {
4808 Diag(Tok, DiagID: DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4809 : diag::warn_pragma_expected_colon)
4810 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
4811 }
4812 if (Kind == OMPC_doacross) {
4813 if (Tok.is(K: tok::identifier) &&
4814 Tok.getIdentifierInfo()->isStr(Str: "omp_cur_iteration")) {
4815 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
4816 ? OMPC_DOACROSS_source_omp_cur_iteration
4817 : OMPC_DOACROSS_sink_omp_cur_iteration;
4818 ConsumeToken();
4819 }
4820 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
4821 if (Tok.isNot(K: tok::minus)) {
4822 Diag(Tok, DiagID: diag::err_omp_sink_and_source_iteration_not_allowd)
4823 << getOpenMPClauseName(C: Kind) << 0 << 0;
4824 SkipUntil(T: tok::r_paren);
4825 return false;
4826 } else {
4827 ConsumeToken();
4828 SourceLocation Loc = Tok.getLocation();
4829 uint64_t Value = 0;
4830 if (Tok.isNot(K: tok::numeric_constant) ||
4831 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
4832 Diag(Loc, DiagID: diag::err_omp_sink_and_source_iteration_not_allowd)
4833 << getOpenMPClauseName(C: Kind) << 0 << 0;
4834 SkipUntil(T: tok::r_paren);
4835 return false;
4836 }
4837 }
4838 }
4839 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
4840 if (Tok.isNot(K: tok::r_paren)) {
4841 Diag(Tok, DiagID: diag::err_omp_sink_and_source_iteration_not_allowd)
4842 << getOpenMPClauseName(C: Kind) << 1 << 1;
4843 SkipUntil(T: tok::r_paren);
4844 return false;
4845 }
4846 }
4847 // Only the 'sink' case has the expression list.
4848 if (Kind == OMPC_doacross &&
4849 (Data.ExtraModifier == OMPC_DOACROSS_source ||
4850 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
4851 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
4852 // Parse ')'.
4853 T.consumeClose();
4854 return false;
4855 }
4856 }
4857 } else if (Kind == OMPC_linear) {
4858 // Try to parse modifier if any.
4859 Data.ExtraModifier = OMPC_LINEAR_val;
4860 if (Tok.is(K: tok::identifier) && PP.LookAhead(N: 0).is(K: tok::l_paren)) {
4861 Data.ExtraModifier =
4862 getOpenMPSimpleClauseType(Kind, Str: PP.getSpelling(Tok), LangOpts: getLangOpts());
4863 Data.ExtraModifierLoc = ConsumeToken();
4864 LinearT.consumeOpen();
4865 NeedRParenForLinear = true;
4866 if (getLangOpts().OpenMP >= 52)
4867 Diag(Loc: Data.ExtraModifierLoc, DiagID: diag::err_omp_deprecate_old_syntax)
4868 << "linear-modifier(list)" << getOpenMPClauseName(C: Kind)
4869 << "linear(list: [linear-modifier,] step(step-size))";
4870 }
4871 } else if (Kind == OMPC_lastprivate) {
4872 // Try to parse modifier if any.
4873 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
4874 // Conditional modifier allowed only in OpenMP 5.0 and not supported in
4875 // distribute and taskloop based directives.
4876 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
4877 !isOpenMPTaskLoopDirective(DKind)) &&
4878 Tok.is(K: tok::identifier) && PP.LookAhead(N: 0).is(K: tok::colon)) {
4879 Data.ExtraModifier =
4880 getOpenMPSimpleClauseType(Kind, Str: PP.getSpelling(Tok), LangOpts: getLangOpts());
4881 Data.ExtraModifierLoc = Tok.getLocation();
4882 ConsumeToken();
4883 assert(Tok.is(tok::colon) && "Expected colon.");
4884 Data.ColonLoc = ConsumeToken();
4885 }
4886 } else if (Kind == OMPC_map) {
4887 // Handle optional iterator map modifier.
4888 if (Tok.is(K: tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4889 HasIterator = true;
4890 EnterScope(ScopeFlags: Scope::OpenMPDirectiveScope | Scope::DeclScope);
4891 Data.MapTypeModifiers.push_back(Elt: OMPC_MAP_MODIFIER_iterator);
4892 Data.MapTypeModifiersLoc.push_back(Elt: Tok.getLocation());
4893 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4894 Data.IteratorExpr = IteratorRes.get();
4895 // Parse ','
4896 ExpectAndConsume(ExpectedTok: tok::comma);
4897 if (getLangOpts().OpenMP < 52) {
4898 Diag(Tok, DiagID: diag::err_omp_unknown_map_type_modifier)
4899 << (getLangOpts().OpenMP >= 51 ? 1 : 0)
4900 << getLangOpts().OpenMPExtensions << 0;
4901 InvalidIterator = true;
4902 }
4903 }
4904 // Handle map type for map clause.
4905 ColonProtectionRAIIObject ColonRAII(*this);
4906
4907 // The first identifier may be a list item, a map-type or a
4908 // map-type-modifier. The map-type can also be delete which has the same
4909 // spelling of the C++ delete keyword.
4910 Data.ExtraModifier = OMPC_MAP_unknown;
4911 Data.ExtraModifierLoc = Tok.getLocation();
4912
4913 // Check for presence of a colon in the map clause.
4914 TentativeParsingAction TPA(*this);
4915 bool ColonPresent = false;
4916 if (SkipUntil(T1: tok::colon, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
4917 Flags: StopBeforeMatch)) {
4918 if (Tok.is(K: tok::colon))
4919 ColonPresent = true;
4920 }
4921 TPA.Revert();
4922 // Only parse map-type-modifier[s] and map-type if a colon is present in
4923 // the map clause.
4924 if (ColonPresent) {
4925 if (getLangOpts().OpenMP >= 60 && getCurToken().is(K: tok::colon))
4926 Diag(Tok, DiagID: diag::err_omp_map_modifier_specification_list);
4927 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
4928 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
4929 parseMapType(P&: *this, Data);
4930 else
4931 SkipUntil(T1: tok::colon, T2: tok::annot_pragma_openmp_end, Flags: StopBeforeMatch);
4932 }
4933 if (Data.ExtraModifier == OMPC_MAP_unknown) {
4934 Data.ExtraModifier = OMPC_MAP_tofrom;
4935 if (getLangOpts().OpenMP >= 52) {
4936 if (DKind == OMPD_target_enter_data)
4937 Data.ExtraModifier = OMPC_MAP_to;
4938 else if (DKind == OMPD_target_exit_data)
4939 Data.ExtraModifier = OMPC_MAP_from;
4940 }
4941 Data.IsMapTypeImplicit = true;
4942 }
4943
4944 if (Tok.is(K: tok::colon))
4945 Data.ColonLoc = ConsumeToken();
4946 } else if (Kind == OMPC_to || Kind == OMPC_from) {
4947 while (Tok.is(K: tok::identifier)) {
4948 auto Modifier = static_cast<OpenMPMotionModifierKind>(
4949 getOpenMPSimpleClauseType(Kind, Str: PP.getSpelling(Tok), LangOpts: getLangOpts()));
4950 if (Modifier == OMPC_MOTION_MODIFIER_unknown)
4951 break;
4952 Data.MotionModifiers.push_back(Elt: Modifier);
4953 Data.MotionModifiersLoc.push_back(Elt: Tok.getLocation());
4954 if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {
4955 ExprResult Tail;
4956 Tail = ParseOpenMPIteratorsExpr();
4957 Tail = Actions.ActOnFinishFullExpr(Expr: Tail.get(), CC: T.getOpenLocation(),
4958 /*DiscardedValue=*/false);
4959 if (Tail.isUsable())
4960 Data.IteratorExpr = Tail.get();
4961 } else {
4962 ConsumeToken();
4963 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
4964 IsInvalidMapperModifier = parseMapperModifier(Data);
4965 if (IsInvalidMapperModifier)
4966 break;
4967 }
4968 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
4969 if (getLangOpts().OpenMP < 51)
4970 break;
4971 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
4972 // TODO: Is that intentional?
4973 if (Tok.is(K: tok::comma))
4974 ConsumeToken();
4975 }
4976 }
4977 if (!Data.MotionModifiers.empty() && Tok.isNot(K: tok::colon)) {
4978 if (!IsInvalidMapperModifier) {
4979 if (getLangOpts().OpenMP < 51)
4980 Diag(Tok, DiagID: diag::warn_pragma_expected_colon) << ")";
4981 else
4982 Diag(Tok, DiagID: diag::warn_pragma_expected_colon) << "motion modifier";
4983 }
4984 SkipUntil(T1: tok::colon, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
4985 Flags: StopBeforeMatch);
4986 }
4987 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
4988 // that intentional?
4989 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
4990 Tok.is(K: tok::colon))
4991 Data.ColonLoc = ConsumeToken();
4992 } else if (Kind == OMPC_allocate ||
4993 (Kind == OMPC_affinity && Tok.is(K: tok::identifier) &&
4994 PP.getSpelling(Tok) == "iterator")) {
4995 // Handle optional allocator and align modifiers followed by colon
4996 // delimiter.
4997 ColonProtectionRAIIObject ColonRAII(*this);
4998 TentativeParsingAction TPA(*this);
4999 // OpenMP 5.0, 2.10.1, task Construct.
5000 // where aff-modifier is one of the following:
5001 // iterator(iterators-definition)
5002 ExprResult Tail;
5003 if (Kind == OMPC_allocate) {
5004 Tail = parseOpenMPAllocateClauseModifiers(P&: *this, Kind, Data);
5005 } else {
5006 HasIterator = true;
5007 EnterScope(ScopeFlags: Scope::OpenMPDirectiveScope | Scope::DeclScope);
5008 Tail = ParseOpenMPIteratorsExpr();
5009 }
5010 Tail = Actions.ActOnFinishFullExpr(Expr: Tail.get(), CC: T.getOpenLocation(),
5011 /*DiscardedValue=*/false);
5012 if (Tail.isUsable() || Data.AllocateAlignment) {
5013 if (Tok.is(K: tok::colon)) {
5014 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
5015 Data.ColonLoc = ConsumeToken();
5016 TPA.Commit();
5017 } else {
5018 // Colon not found, parse only list of variables.
5019 TPA.Revert();
5020 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
5021 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openmp_end,
5022 Flags: StopBeforeMatch);
5023 Diag(Tok, DiagID: diag::err_modifier_expected_colon) << "allocate clause";
5024 }
5025 }
5026 } else {
5027 // Parsing was unsuccessfull, revert and skip to the end of clause or
5028 // directive.
5029 TPA.Revert();
5030 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
5031 Flags: StopBeforeMatch);
5032 }
5033 } else if (Kind == OMPC_adjust_args) {
5034 // Handle adjust-op for adjust_args clause.
5035 ColonProtectionRAIIObject ColonRAII(*this);
5036 Data.ExtraModifier = getOpenMPSimpleClauseType(
5037 Kind, Str: Tok.is(K: tok::identifier) ? PP.getSpelling(Tok) : "",
5038 LangOpts: getLangOpts());
5039 Data.ExtraModifierLoc = Tok.getLocation();
5040 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
5041 Diag(Tok, DiagID: diag::err_omp_unknown_adjust_args_op)
5042 << (getLangOpts().OpenMP >= 60 ? 1 : 0);
5043 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openmp_end, Flags: StopBeforeMatch);
5044 } else {
5045 ConsumeToken();
5046 if (Tok.is(K: tok::colon))
5047 Data.ColonLoc = Tok.getLocation();
5048 if (getLangOpts().OpenMP >= 61) {
5049 // Handle the optional fallback argument for the need_device_ptr
5050 // modifier.
5051 if (Tok.is(K: tok::l_paren)) {
5052 BalancedDelimiterTracker T(*this, tok::l_paren);
5053 T.consumeOpen();
5054 if (Tok.is(K: tok::identifier)) {
5055 std::string Modifier = PP.getSpelling(Tok);
5056 if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {
5057 Data.NeedDevicePtrModifier =
5058 Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify
5059 : OMPC_NEED_DEVICE_PTR_fb_preserve;
5060 } else {
5061 Diag(Tok, DiagID: diag::err_omp_unknown_need_device_ptr_kind);
5062 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openmp_end,
5063 Flags: StopBeforeMatch);
5064 return false;
5065 }
5066 ConsumeToken();
5067 if (Tok.is(K: tok::r_paren)) {
5068 Data.NeedDevicePtrModifierLoc = Tok.getLocation();
5069 ConsumeAnyToken();
5070 } else {
5071 Diag(Tok, DiagID: diag::err_expected) << tok::r_paren;
5072 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openmp_end,
5073 Flags: StopBeforeMatch);
5074 return false;
5075 }
5076 } else {
5077 Data.NeedDevicePtrModifier = OMPC_NEED_DEVICE_PTR_unknown;
5078 }
5079 }
5080 }
5081 ExpectAndConsume(ExpectedTok: tok::colon, Diag: diag::warn_pragma_expected_colon,
5082 DiagMsg: "adjust-op");
5083 }
5084 } else if (Kind == OMPC_use_device_ptr) {
5085 // Handle optional fallback modifier for use_device_ptr clause.
5086 // use_device_ptr([fb_preserve | fb_nullify :] list)
5087 Data.ExtraModifier = OMPC_USE_DEVICE_PTR_FALLBACK_unknown;
5088 if (getLangOpts().OpenMP >= 61 && Tok.is(K: tok::identifier)) {
5089 auto FallbackModifier = static_cast<OpenMPUseDevicePtrFallbackModifier>(
5090 getOpenMPSimpleClauseType(Kind, Str: PP.getSpelling(Tok), LangOpts: getLangOpts()));
5091 if (FallbackModifier != OMPC_USE_DEVICE_PTR_FALLBACK_unknown) {
5092 Data.ExtraModifier = FallbackModifier;
5093 Data.ExtraModifierLoc = Tok.getLocation();
5094 ConsumeToken();
5095 if (Tok.is(K: tok::colon))
5096 Data.ColonLoc = ConsumeToken();
5097 else
5098 Diag(Tok, DiagID: diag::err_modifier_expected_colon) << "fallback";
5099 }
5100 }
5101 } // Handle num_teams clause with optional lower-bound:upper-bound syntax
5102 if (Kind == OMPC_num_teams && !Tok.is(K: tok::r_paren) &&
5103 !Tok.is(K: tok::annot_pragma_openmp_end)) {
5104 ExprResult FirstExpr = ParseAssignmentExpression();
5105 if (FirstExpr.isInvalid()) {
5106 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openmp_end, Flags: StopBeforeMatch);
5107 Data.RLoc = Tok.getLocation();
5108 if (!T.consumeClose())
5109 Data.RLoc = T.getCloseLocation();
5110 return true;
5111 }
5112
5113 if (Tok.is(K: tok::colon)) {
5114 // Lower-bound:upper-bound syntax
5115 ConsumeToken();
5116 ExprResult UpperBound = ParseAssignmentExpression();
5117 if (UpperBound.isInvalid()) {
5118 SkipUntil(T1: tok::r_paren, T2: tok::annot_pragma_openmp_end, Flags: StopBeforeMatch);
5119 Data.RLoc = Tok.getLocation();
5120 if (!T.consumeClose())
5121 Data.RLoc = T.getCloseLocation();
5122 return true;
5123 }
5124 Vars.push_back(Elt: FirstExpr.get()); // lower-bound
5125 Vars.push_back(Elt: UpperBound.get()); // upper-bound
5126 Data.RLoc = Tok.getLocation();
5127 if (!T.consumeClose())
5128 Data.RLoc = T.getCloseLocation();
5129 return false; // Success
5130 }
5131 if (Tok.is(K: tok::comma)) {
5132 Vars.push_back(Elt: FirstExpr.get());
5133 while (Tok.is(K: tok::comma)) {
5134 ConsumeToken();
5135 ExprResult NextExpr = ParseAssignmentExpression();
5136 if (NextExpr.isUsable()) {
5137 Vars.push_back(Elt: NextExpr.get());
5138 } else {
5139 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
5140 Flags: StopBeforeMatch);
5141 break;
5142 }
5143 }
5144 Data.RLoc = Tok.getLocation();
5145 bool HadError = T.consumeClose();
5146 if (!HadError)
5147 Data.RLoc = T.getCloseLocation();
5148 return HadError;
5149 }
5150
5151 // Single value - parse closing paren
5152 Vars.push_back(Elt: FirstExpr.get());
5153 Data.RLoc = Tok.getLocation();
5154 if (!T.consumeClose())
5155 Data.RLoc = T.getCloseLocation();
5156 return false; // Success
5157 }
5158
5159 bool IsComma =
5160 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
5161 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
5162 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
5163 (Kind == OMPC_reduction && !InvalidReductionId) ||
5164 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
5165 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
5166 (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
5167 (Kind == OMPC_adjust_args &&
5168 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
5169 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
5170 while (IsComma || (Tok.isNot(K: tok::r_paren) && Tok.isNot(K: tok::colon) &&
5171 Tok.isNot(K: tok::annot_pragma_openmp_end))) {
5172 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
5173 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
5174 if (!ParseOpenMPReservedLocator(Kind, Data, LangOpts: getLangOpts())) {
5175 // Parse variable
5176 ExprResult VarExpr = ParseAssignmentExpression();
5177 if (VarExpr.isUsable()) {
5178 Vars.push_back(Elt: VarExpr.get());
5179 } else {
5180 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
5181 Flags: StopBeforeMatch);
5182 }
5183 }
5184 // Skip ',' if any
5185 IsComma = Tok.is(K: tok::comma);
5186 if (IsComma)
5187 ConsumeToken();
5188 else if (Tok.isNot(K: tok::r_paren) &&
5189 Tok.isNot(K: tok::annot_pragma_openmp_end) &&
5190 (!MayHaveTail || Tok.isNot(K: tok::colon))) {
5191 unsigned OMPVersion = Actions.getLangOpts().OpenMP;
5192 Diag(Tok, DiagID: diag::err_omp_expected_punc)
5193 << ((Kind == OMPC_flush)
5194 ? getOpenMPDirectiveName(D: OMPD_flush, Ver: OMPVersion)
5195 : getOpenMPClauseName(C: Kind))
5196 << (Kind == OMPC_flush);
5197 }
5198 }
5199
5200 // Parse ')' for linear clause with modifier.
5201 if (NeedRParenForLinear)
5202 LinearT.consumeClose();
5203 // Parse ':' linear modifiers (val, uval, ref or step(step-size))
5204 // or parse ':' alignment.
5205 const bool MustHaveTail = MayHaveTail && Tok.is(K: tok::colon);
5206 bool StepFound = false;
5207 bool ModifierFound = false;
5208 if (MustHaveTail) {
5209 Data.ColonLoc = Tok.getLocation();
5210 SourceLocation ELoc = ConsumeToken();
5211
5212 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
5213 bool Malformed = false;
5214 while (Tok.isNot(K: tok::r_paren)) {
5215 if (Tok.is(K: tok::identifier)) {
5216 // identifier could be a linear kind (val, uval, ref) or step
5217 // modifier or step size
5218 OpenMPLinearClauseKind LinKind =
5219 static_cast<OpenMPLinearClauseKind>(getOpenMPSimpleClauseType(
5220 Kind, Str: Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
5221 LangOpts: getLangOpts()));
5222
5223 if (LinKind == OMPC_LINEAR_step) {
5224 if (StepFound)
5225 Diag(Tok, DiagID: diag::err_omp_multiple_step_or_linear_modifier) << 0;
5226
5227 BalancedDelimiterTracker StepT(*this, tok::l_paren,
5228 tok::annot_pragma_openmp_end);
5229 SourceLocation StepModifierLoc = ConsumeToken();
5230 // parse '('
5231 if (StepT.consumeOpen())
5232 Diag(Loc: StepModifierLoc, DiagID: diag::err_expected_lparen_after) << "step";
5233
5234 // parse step size expression
5235 StepFound = parseStepSize(P&: *this, Data, CKind: Kind, ELoc: Tok.getLocation());
5236 if (StepFound)
5237 Data.StepModifierLoc = StepModifierLoc;
5238
5239 // parse ')'
5240 StepT.consumeClose();
5241 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
5242 if (ModifierFound)
5243 Diag(Tok, DiagID: diag::err_omp_multiple_step_or_linear_modifier) << 1;
5244
5245 Data.ExtraModifier = LinKind;
5246 Data.ExtraModifierLoc = ConsumeToken();
5247 ModifierFound = true;
5248 } else {
5249 StepFound = parseStepSize(P&: *this, Data, CKind: Kind, ELoc: Tok.getLocation());
5250 if (!StepFound) {
5251 Malformed = true;
5252 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
5253 Flags: StopBeforeMatch);
5254 }
5255 }
5256 } else {
5257 // parse an integer expression as step size
5258 StepFound = parseStepSize(P&: *this, Data, CKind: Kind, ELoc: Tok.getLocation());
5259 }
5260
5261 if (Tok.is(K: tok::comma))
5262 ConsumeToken();
5263 if (Tok.is(K: tok::r_paren) || Tok.is(K: tok::annot_pragma_openmp_end))
5264 break;
5265 }
5266 if (!Malformed && !StepFound && !ModifierFound)
5267 Diag(Loc: ELoc, DiagID: diag::err_expected_expression);
5268 } else {
5269 // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
5270 ExprResult Tail = ParseAssignmentExpression();
5271 Tail = Actions.ActOnFinishFullExpr(Expr: Tail.get(), CC: ELoc,
5272 /*DiscardedValue*/ false);
5273 if (Tail.isUsable())
5274 Data.DepModOrTailExpr = Tail.get();
5275 else
5276 SkipUntil(T1: tok::comma, T2: tok::r_paren, T3: tok::annot_pragma_openmp_end,
5277 Flags: StopBeforeMatch);
5278 }
5279 }
5280
5281 // Parse ')'.
5282 Data.RLoc = Tok.getLocation();
5283 if (!T.consumeClose())
5284 Data.RLoc = T.getCloseLocation();
5285 // Exit from scope when the iterator is used in depend clause.
5286 if (HasIterator)
5287 ExitScope();
5288 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
5289 Vars.empty()) ||
5290 (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
5291 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
5292}
5293
5294OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5295 OpenMPClauseKind Kind,
5296 bool ParseOnly) {
5297 SourceLocation Loc = Tok.getLocation();
5298 SourceLocation LOpen = ConsumeToken();
5299 SmallVector<Expr *, 4> Vars;
5300 SemaOpenMP::OpenMPVarListDataTy Data;
5301
5302 if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
5303 return nullptr;
5304
5305 if (ParseOnly)
5306 return nullptr;
5307 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5308 return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5309}
5310
5311bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5312 SourceLocation &ClauseNameLoc,
5313 SourceLocation &OpenLoc,
5314 SourceLocation &CloseLoc,
5315 SmallVectorImpl<Expr *> &Exprs,
5316 bool ReqIntConst) {
5317 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5318 "Expected parsing to start at clause name");
5319 ClauseNameLoc = ConsumeToken();
5320
5321 // Parse inside of '(' and ')'.
5322 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5323 if (T.consumeOpen()) {
5324 Diag(Tok, DiagID: diag::err_expected) << tok::l_paren;
5325 return true;
5326 }
5327
5328 // Parse the list with interleaved commas.
5329 do {
5330 ExprResult Val =
5331 ReqIntConst ? ParseConstantExpression() : ParseAssignmentExpression();
5332 if (!Val.isUsable()) {
5333 // Encountered something other than an expression; abort to ')'.
5334 T.skipToEnd();
5335 return true;
5336 }
5337 Exprs.push_back(Elt: Val.get());
5338 } while (TryConsumeToken(Expected: tok::comma));
5339
5340 bool Result = T.consumeClose();
5341 OpenLoc = T.getOpenLocation();
5342 CloseLoc = T.getCloseLocation();
5343 return Result;
5344}
5345