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