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