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