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