• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/AST/StmtOpenMP.h"
16 #include "clang/Basic/OpenMPKinds.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Basic/TokenKinds.h"
19 #include "clang/Parse/ParseDiagnostic.h"
20 #include "clang/Parse/Parser.h"
21 #include "clang/Parse/RAIIObjectsForParser.h"
22 #include "clang/Sema/Scope.h"
23 #include "llvm/ADT/PointerIntPair.h"
24 #include "llvm/ADT/UniqueVector.h"
25 #include "llvm/Frontend/OpenMP/OMPContext.h"
26 
27 using namespace clang;
28 using namespace llvm::omp;
29 
30 //===----------------------------------------------------------------------===//
31 // OpenMP declarative directives.
32 //===----------------------------------------------------------------------===//
33 
34 namespace {
35 enum OpenMPDirectiveKindEx {
36   OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
37   OMPD_data,
38   OMPD_declare,
39   OMPD_end,
40   OMPD_end_declare,
41   OMPD_enter,
42   OMPD_exit,
43   OMPD_point,
44   OMPD_reduction,
45   OMPD_target_enter,
46   OMPD_target_exit,
47   OMPD_update,
48   OMPD_distribute_parallel,
49   OMPD_teams_distribute_parallel,
50   OMPD_target_teams_distribute_parallel,
51   OMPD_mapper,
52   OMPD_variant,
53   OMPD_begin,
54   OMPD_begin_declare,
55 };
56 
57 // Helper to unify the enum class OpenMPDirectiveKind with its extension
58 // the OpenMPDirectiveKindEx enum which allows to use them together as if they
59 // are unsigned values.
60 struct OpenMPDirectiveKindExWrapper {
OpenMPDirectiveKindExWrapper__anon755a15050111::OpenMPDirectiveKindExWrapper61   OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
OpenMPDirectiveKindExWrapper__anon755a15050111::OpenMPDirectiveKindExWrapper62   OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
operator ==__anon755a15050111::OpenMPDirectiveKindExWrapper63   bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
operator !=__anon755a15050111::OpenMPDirectiveKindExWrapper64   bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
operator <__anon755a15050111::OpenMPDirectiveKindExWrapper65   bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
operator unsigned__anon755a15050111::OpenMPDirectiveKindExWrapper66   operator unsigned() const { return Value; }
operator OpenMPDirectiveKind__anon755a15050111::OpenMPDirectiveKindExWrapper67   operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
68   unsigned Value;
69 };
70 
71 class DeclDirectiveListParserHelper final {
72   SmallVector<Expr *, 4> Identifiers;
73   Parser *P;
74   OpenMPDirectiveKind Kind;
75 
76 public:
DeclDirectiveListParserHelper(Parser * P,OpenMPDirectiveKind Kind)77   DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
78       : P(P), Kind(Kind) {}
operator ()(CXXScopeSpec & SS,DeclarationNameInfo NameInfo)79   void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
80     ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
81         P->getCurScope(), SS, NameInfo, Kind);
82     if (Res.isUsable())
83       Identifiers.push_back(Res.get());
84   }
getIdentifiers() const85   llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
86 };
87 } // namespace
88 
89 // Map token string to extended OMP token kind that are
90 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
getOpenMPDirectiveKindEx(StringRef S)91 static unsigned getOpenMPDirectiveKindEx(StringRef S) {
92   OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
93   if (DKind != OMPD_unknown)
94     return DKind;
95 
96   return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
97       .Case("cancellation", OMPD_cancellation)
98       .Case("data", OMPD_data)
99       .Case("declare", OMPD_declare)
100       .Case("end", OMPD_end)
101       .Case("enter", OMPD_enter)
102       .Case("exit", OMPD_exit)
103       .Case("point", OMPD_point)
104       .Case("reduction", OMPD_reduction)
105       .Case("update", OMPD_update)
106       .Case("mapper", OMPD_mapper)
107       .Case("variant", OMPD_variant)
108       .Case("begin", OMPD_begin)
109       .Default(OMPD_unknown);
110 }
111 
parseOpenMPDirectiveKind(Parser & P)112 static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
113   // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
114   // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
115   // TODO: add other combined directives in topological order.
116   static const OpenMPDirectiveKindExWrapper F[][3] = {
117       {OMPD_begin, OMPD_declare, OMPD_begin_declare},
118       {OMPD_end, OMPD_declare, OMPD_end_declare},
119       {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
120       {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
121       {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
122       {OMPD_declare, OMPD_simd, OMPD_declare_simd},
123       {OMPD_declare, OMPD_target, OMPD_declare_target},
124       {OMPD_declare, OMPD_variant, OMPD_declare_variant},
125       {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
126       {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
127       {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
128       {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
129       {OMPD_distribute_parallel_for, OMPD_simd,
130        OMPD_distribute_parallel_for_simd},
131       {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
132       {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
133       {OMPD_target, OMPD_data, OMPD_target_data},
134       {OMPD_target, OMPD_enter, OMPD_target_enter},
135       {OMPD_target, OMPD_exit, OMPD_target_exit},
136       {OMPD_target, OMPD_update, OMPD_target_update},
137       {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
138       {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
139       {OMPD_for, OMPD_simd, OMPD_for_simd},
140       {OMPD_parallel, OMPD_for, OMPD_parallel_for},
141       {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
142       {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
143       {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
144       {OMPD_target, OMPD_parallel, OMPD_target_parallel},
145       {OMPD_target, OMPD_simd, OMPD_target_simd},
146       {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
147       {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
148       {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
149       {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
150       {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
151       {OMPD_teams_distribute_parallel, OMPD_for,
152        OMPD_teams_distribute_parallel_for},
153       {OMPD_teams_distribute_parallel_for, OMPD_simd,
154        OMPD_teams_distribute_parallel_for_simd},
155       {OMPD_target, OMPD_teams, OMPD_target_teams},
156       {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
157       {OMPD_target_teams_distribute, OMPD_parallel,
158        OMPD_target_teams_distribute_parallel},
159       {OMPD_target_teams_distribute, OMPD_simd,
160        OMPD_target_teams_distribute_simd},
161       {OMPD_target_teams_distribute_parallel, OMPD_for,
162        OMPD_target_teams_distribute_parallel_for},
163       {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
164        OMPD_target_teams_distribute_parallel_for_simd},
165       {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
166       {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
167       {OMPD_parallel, OMPD_master, OMPD_parallel_master},
168       {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
169       {OMPD_parallel_master_taskloop, OMPD_simd,
170        OMPD_parallel_master_taskloop_simd}};
171   enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
172   Token Tok = P.getCurToken();
173   OpenMPDirectiveKindExWrapper DKind =
174       Tok.isAnnotation()
175           ? static_cast<unsigned>(OMPD_unknown)
176           : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
177   if (DKind == OMPD_unknown)
178     return OMPD_unknown;
179 
180   for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
181     if (DKind != F[I][0])
182       continue;
183 
184     Tok = P.getPreprocessor().LookAhead(0);
185     OpenMPDirectiveKindExWrapper SDKind =
186         Tok.isAnnotation()
187             ? static_cast<unsigned>(OMPD_unknown)
188             : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
189     if (SDKind == OMPD_unknown)
190       continue;
191 
192     if (SDKind == F[I][1]) {
193       P.ConsumeToken();
194       DKind = F[I][2];
195     }
196   }
197   return unsigned(DKind) < llvm::omp::Directive_enumSize
198              ? static_cast<OpenMPDirectiveKind>(DKind)
199              : OMPD_unknown;
200 }
201 
parseOpenMPReductionId(Parser & P)202 static DeclarationName parseOpenMPReductionId(Parser &P) {
203   Token Tok = P.getCurToken();
204   Sema &Actions = P.getActions();
205   OverloadedOperatorKind OOK = OO_None;
206   // Allow to use 'operator' keyword for C++ operators
207   bool WithOperator = false;
208   if (Tok.is(tok::kw_operator)) {
209     P.ConsumeToken();
210     Tok = P.getCurToken();
211     WithOperator = true;
212   }
213   switch (Tok.getKind()) {
214   case tok::plus: // '+'
215     OOK = OO_Plus;
216     break;
217   case tok::minus: // '-'
218     OOK = OO_Minus;
219     break;
220   case tok::star: // '*'
221     OOK = OO_Star;
222     break;
223   case tok::amp: // '&'
224     OOK = OO_Amp;
225     break;
226   case tok::pipe: // '|'
227     OOK = OO_Pipe;
228     break;
229   case tok::caret: // '^'
230     OOK = OO_Caret;
231     break;
232   case tok::ampamp: // '&&'
233     OOK = OO_AmpAmp;
234     break;
235   case tok::pipepipe: // '||'
236     OOK = OO_PipePipe;
237     break;
238   case tok::identifier: // identifier
239     if (!WithOperator)
240       break;
241     LLVM_FALLTHROUGH;
242   default:
243     P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
244     P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
245                 Parser::StopBeforeMatch);
246     return DeclarationName();
247   }
248   P.ConsumeToken();
249   auto &DeclNames = Actions.getASTContext().DeclarationNames;
250   return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
251                         : DeclNames.getCXXOperatorName(OOK);
252 }
253 
254 /// Parse 'omp declare reduction' construct.
255 ///
256 ///       declare-reduction-directive:
257 ///        annot_pragma_openmp 'declare' 'reduction'
258 ///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
259 ///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
260 ///        annot_pragma_openmp_end
261 /// <reduction_id> is either a base language identifier or one of the following
262 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
263 ///
264 Parser::DeclGroupPtrTy
ParseOpenMPDeclareReductionDirective(AccessSpecifier AS)265 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
266   // Parse '('.
267   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
268   if (T.expectAndConsume(
269           diag::err_expected_lparen_after,
270           getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
271     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
272     return DeclGroupPtrTy();
273   }
274 
275   DeclarationName Name = parseOpenMPReductionId(*this);
276   if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
277     return DeclGroupPtrTy();
278 
279   // Consume ':'.
280   bool IsCorrect = !ExpectAndConsume(tok::colon);
281 
282   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
283     return DeclGroupPtrTy();
284 
285   IsCorrect = IsCorrect && !Name.isEmpty();
286 
287   if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
288     Diag(Tok.getLocation(), diag::err_expected_type);
289     IsCorrect = false;
290   }
291 
292   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
293     return DeclGroupPtrTy();
294 
295   SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
296   // Parse list of types until ':' token.
297   do {
298     ColonProtectionRAIIObject ColonRAII(*this);
299     SourceRange Range;
300     TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS);
301     if (TR.isUsable()) {
302       QualType ReductionType =
303           Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
304       if (!ReductionType.isNull()) {
305         ReductionTypes.push_back(
306             std::make_pair(ReductionType, Range.getBegin()));
307       }
308     } else {
309       SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
310                 StopBeforeMatch);
311     }
312 
313     if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
314       break;
315 
316     // Consume ','.
317     if (ExpectAndConsume(tok::comma)) {
318       IsCorrect = false;
319       if (Tok.is(tok::annot_pragma_openmp_end)) {
320         Diag(Tok.getLocation(), diag::err_expected_type);
321         return DeclGroupPtrTy();
322       }
323     }
324   } while (Tok.isNot(tok::annot_pragma_openmp_end));
325 
326   if (ReductionTypes.empty()) {
327     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
328     return DeclGroupPtrTy();
329   }
330 
331   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
332     return DeclGroupPtrTy();
333 
334   // Consume ':'.
335   if (ExpectAndConsume(tok::colon))
336     IsCorrect = false;
337 
338   if (Tok.is(tok::annot_pragma_openmp_end)) {
339     Diag(Tok.getLocation(), diag::err_expected_expression);
340     return DeclGroupPtrTy();
341   }
342 
343   DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
344       getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
345 
346   // Parse <combiner> expression and then parse initializer if any for each
347   // correct type.
348   unsigned I = 0, E = ReductionTypes.size();
349   for (Decl *D : DRD.get()) {
350     TentativeParsingAction TPA(*this);
351     ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
352                                     Scope::CompoundStmtScope |
353                                     Scope::OpenMPDirectiveScope);
354     // Parse <combiner> expression.
355     Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
356     ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
357         ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
358     Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
359 
360     if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
361         Tok.isNot(tok::annot_pragma_openmp_end)) {
362       TPA.Commit();
363       IsCorrect = false;
364       break;
365     }
366     IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
367     ExprResult InitializerResult;
368     if (Tok.isNot(tok::annot_pragma_openmp_end)) {
369       // Parse <initializer> expression.
370       if (Tok.is(tok::identifier) &&
371           Tok.getIdentifierInfo()->isStr("initializer")) {
372         ConsumeToken();
373       } else {
374         Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
375         TPA.Commit();
376         IsCorrect = false;
377         break;
378       }
379       // Parse '('.
380       BalancedDelimiterTracker T(*this, tok::l_paren,
381                                  tok::annot_pragma_openmp_end);
382       IsCorrect =
383           !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
384           IsCorrect;
385       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
386         ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
387                                         Scope::CompoundStmtScope |
388                                         Scope::OpenMPDirectiveScope);
389         // Parse expression.
390         VarDecl *OmpPrivParm =
391             Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
392                                                                 D);
393         // Check if initializer is omp_priv <init_expr> or something else.
394         if (Tok.is(tok::identifier) &&
395             Tok.getIdentifierInfo()->isStr("omp_priv")) {
396           ConsumeToken();
397           ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
398         } else {
399           InitializerResult = Actions.ActOnFinishFullExpr(
400               ParseAssignmentExpression().get(), D->getLocation(),
401               /*DiscardedValue*/ false);
402         }
403         Actions.ActOnOpenMPDeclareReductionInitializerEnd(
404             D, InitializerResult.get(), OmpPrivParm);
405         if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
406             Tok.isNot(tok::annot_pragma_openmp_end)) {
407           TPA.Commit();
408           IsCorrect = false;
409           break;
410         }
411         IsCorrect =
412             !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
413       }
414     }
415 
416     ++I;
417     // Revert parsing if not the last type, otherwise accept it, we're done with
418     // parsing.
419     if (I != E)
420       TPA.Revert();
421     else
422       TPA.Commit();
423   }
424   return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
425                                                          IsCorrect);
426 }
427 
ParseOpenMPReductionInitializerForDecl(VarDecl * OmpPrivParm)428 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
429   // Parse declarator '=' initializer.
430   // If a '==' or '+=' is found, suggest a fixit to '='.
431   if (isTokenEqualOrEqualTypo()) {
432     ConsumeToken();
433 
434     if (Tok.is(tok::code_completion)) {
435       Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
436       Actions.FinalizeDeclaration(OmpPrivParm);
437       cutOffParsing();
438       return;
439     }
440 
441     PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
442     ExprResult Init = ParseInitializer();
443 
444     if (Init.isInvalid()) {
445       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
446       Actions.ActOnInitializerError(OmpPrivParm);
447     } else {
448       Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
449                                    /*DirectInit=*/false);
450     }
451   } else if (Tok.is(tok::l_paren)) {
452     // Parse C++ direct initializer: '(' expression-list ')'
453     BalancedDelimiterTracker T(*this, tok::l_paren);
454     T.consumeOpen();
455 
456     ExprVector Exprs;
457     CommaLocsTy CommaLocs;
458 
459     SourceLocation LParLoc = T.getOpenLocation();
460     auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
461       QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
462           getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
463           OmpPrivParm->getLocation(), Exprs, LParLoc);
464       CalledSignatureHelp = true;
465       return PreferredType;
466     };
467     if (ParseExpressionList(Exprs, CommaLocs, [&] {
468           PreferredType.enterFunctionArgument(Tok.getLocation(),
469                                               RunSignatureHelp);
470         })) {
471       if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
472         RunSignatureHelp();
473       Actions.ActOnInitializerError(OmpPrivParm);
474       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
475     } else {
476       // Match the ')'.
477       SourceLocation RLoc = Tok.getLocation();
478       if (!T.consumeClose())
479         RLoc = T.getCloseLocation();
480 
481       assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
482              "Unexpected number of commas!");
483 
484       ExprResult Initializer =
485           Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
486       Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
487                                    /*DirectInit=*/true);
488     }
489   } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
490     // Parse C++0x braced-init-list.
491     Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
492 
493     ExprResult Init(ParseBraceInitializer());
494 
495     if (Init.isInvalid()) {
496       Actions.ActOnInitializerError(OmpPrivParm);
497     } else {
498       Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
499                                    /*DirectInit=*/true);
500     }
501   } else {
502     Actions.ActOnUninitializedDecl(OmpPrivParm);
503   }
504 }
505 
506 /// Parses 'omp declare mapper' directive.
507 ///
508 ///       declare-mapper-directive:
509 ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
510 ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
511 ///         annot_pragma_openmp_end
512 /// <mapper-identifier> and <var> are base language identifiers.
513 ///
514 Parser::DeclGroupPtrTy
ParseOpenMPDeclareMapperDirective(AccessSpecifier AS)515 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
516   bool IsCorrect = true;
517   // Parse '('
518   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
519   if (T.expectAndConsume(diag::err_expected_lparen_after,
520                          getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
521     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
522     return DeclGroupPtrTy();
523   }
524 
525   // Parse <mapper-identifier>
526   auto &DeclNames = Actions.getASTContext().DeclarationNames;
527   DeclarationName MapperId;
528   if (PP.LookAhead(0).is(tok::colon)) {
529     if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
530       Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
531       IsCorrect = false;
532     } else {
533       MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
534     }
535     ConsumeToken();
536     // Consume ':'.
537     ExpectAndConsume(tok::colon);
538   } else {
539     // If no mapper identifier is provided, its name is "default" by default
540     MapperId =
541         DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
542   }
543 
544   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
545     return DeclGroupPtrTy();
546 
547   // Parse <type> <var>
548   DeclarationName VName;
549   QualType MapperType;
550   SourceRange Range;
551   TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
552   if (ParsedType.isUsable())
553     MapperType =
554         Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
555   if (MapperType.isNull())
556     IsCorrect = false;
557   if (!IsCorrect) {
558     SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
559     return DeclGroupPtrTy();
560   }
561 
562   // Consume ')'.
563   IsCorrect &= !T.consumeClose();
564   if (!IsCorrect) {
565     SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
566     return DeclGroupPtrTy();
567   }
568 
569   // Enter scope.
570   DeclarationNameInfo DirName;
571   SourceLocation Loc = Tok.getLocation();
572   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
573                         Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
574   ParseScope OMPDirectiveScope(this, ScopeFlags);
575   Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
576 
577   // Add the mapper variable declaration.
578   ExprResult MapperVarRef = Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
579       getCurScope(), MapperType, Range.getBegin(), VName);
580 
581   // Parse map clauses.
582   SmallVector<OMPClause *, 6> Clauses;
583   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
584     OpenMPClauseKind CKind = Tok.isAnnotation()
585                                  ? OMPC_unknown
586                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
587     Actions.StartOpenMPClause(CKind);
588     OMPClause *Clause =
589         ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
590     if (Clause)
591       Clauses.push_back(Clause);
592     else
593       IsCorrect = false;
594     // Skip ',' if any.
595     if (Tok.is(tok::comma))
596       ConsumeToken();
597     Actions.EndOpenMPClause();
598   }
599   if (Clauses.empty()) {
600     Diag(Tok, diag::err_omp_expected_clause)
601         << getOpenMPDirectiveName(OMPD_declare_mapper);
602     IsCorrect = false;
603   }
604 
605   // Exit scope.
606   Actions.EndOpenMPDSABlock(nullptr);
607   OMPDirectiveScope.Exit();
608   DeclGroupPtrTy DG = Actions.ActOnOpenMPDeclareMapperDirective(
609       getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
610       Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
611   if (!IsCorrect)
612     return DeclGroupPtrTy();
613 
614   return DG;
615 }
616 
parseOpenMPDeclareMapperVarDecl(SourceRange & Range,DeclarationName & Name,AccessSpecifier AS)617 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
618                                                    DeclarationName &Name,
619                                                    AccessSpecifier AS) {
620   // Parse the common declaration-specifiers piece.
621   Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
622   DeclSpec DS(AttrFactory);
623   ParseSpecifierQualifierList(DS, AS, DSC);
624 
625   // Parse the declarator.
626   DeclaratorContext Context = DeclaratorContext::Prototype;
627   Declarator DeclaratorInfo(DS, Context);
628   ParseDeclarator(DeclaratorInfo);
629   Range = DeclaratorInfo.getSourceRange();
630   if (DeclaratorInfo.getIdentifier() == nullptr) {
631     Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
632     return true;
633   }
634   Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
635 
636   return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
637 }
638 
639 namespace {
640 /// RAII that recreates function context for correct parsing of clauses of
641 /// 'declare simd' construct.
642 /// OpenMP, 2.8.2 declare simd Construct
643 /// The expressions appearing in the clauses of this directive are evaluated in
644 /// the scope of the arguments of the function declaration or definition.
645 class FNContextRAII final {
646   Parser &P;
647   Sema::CXXThisScopeRAII *ThisScope;
648   Parser::MultiParseScope Scopes;
649   bool HasFunScope = false;
650   FNContextRAII() = delete;
651   FNContextRAII(const FNContextRAII &) = delete;
652   FNContextRAII &operator=(const FNContextRAII &) = delete;
653 
654 public:
FNContextRAII(Parser & P,Parser::DeclGroupPtrTy Ptr)655   FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {
656     Decl *D = *Ptr.get().begin();
657     NamedDecl *ND = dyn_cast<NamedDecl>(D);
658     RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
659     Sema &Actions = P.getActions();
660 
661     // Allow 'this' within late-parsed attributes.
662     ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
663                                            ND && ND->isCXXInstanceMember());
664 
665     // If the Decl is templatized, add template parameters to scope.
666     // FIXME: Track CurTemplateDepth?
667     P.ReenterTemplateScopes(Scopes, D);
668 
669     // If the Decl is on a function, add function parameters to the scope.
670     if (D->isFunctionOrFunctionTemplate()) {
671       HasFunScope = true;
672       Scopes.Enter(Scope::FnScope | Scope::DeclScope |
673                    Scope::CompoundStmtScope);
674       Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
675     }
676   }
~FNContextRAII()677   ~FNContextRAII() {
678     if (HasFunScope)
679       P.getActions().ActOnExitFunctionContext();
680     delete ThisScope;
681   }
682 };
683 } // namespace
684 
685 /// Parses clauses for 'declare simd' directive.
686 ///    clause:
687 ///      'inbranch' | 'notinbranch'
688 ///      'simdlen' '(' <expr> ')'
689 ///      { 'uniform' '(' <argument_list> ')' }
690 ///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
691 ///      { '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)692 static bool parseDeclareSimdClauses(
693     Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
694     SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
695     SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
696     SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
697   SourceRange BSRange;
698   const Token &Tok = P.getCurToken();
699   bool IsError = false;
700   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
701     if (Tok.isNot(tok::identifier))
702       break;
703     OMPDeclareSimdDeclAttr::BranchStateTy Out;
704     IdentifierInfo *II = Tok.getIdentifierInfo();
705     StringRef ClauseName = II->getName();
706     // Parse 'inranch|notinbranch' clauses.
707     if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
708       if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
709         P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
710             << ClauseName
711             << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
712         IsError = true;
713       }
714       BS = Out;
715       BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
716       P.ConsumeToken();
717     } else if (ClauseName.equals("simdlen")) {
718       if (SimdLen.isUsable()) {
719         P.Diag(Tok, diag::err_omp_more_one_clause)
720             << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
721         IsError = true;
722       }
723       P.ConsumeToken();
724       SourceLocation RLoc;
725       SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
726       if (SimdLen.isInvalid())
727         IsError = true;
728     } else {
729       OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
730       if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
731           CKind == OMPC_linear) {
732         Parser::OpenMPVarListDataTy Data;
733         SmallVectorImpl<Expr *> *Vars = &Uniforms;
734         if (CKind == OMPC_aligned) {
735           Vars = &Aligneds;
736         } else if (CKind == OMPC_linear) {
737           Data.ExtraModifier = OMPC_LINEAR_val;
738           Vars = &Linears;
739         }
740 
741         P.ConsumeToken();
742         if (P.ParseOpenMPVarList(OMPD_declare_simd,
743                                  getOpenMPClauseKind(ClauseName), *Vars, Data))
744           IsError = true;
745         if (CKind == OMPC_aligned) {
746           Alignments.append(Aligneds.size() - Alignments.size(),
747                             Data.DepModOrTailExpr);
748         } else if (CKind == OMPC_linear) {
749           assert(0 <= Data.ExtraModifier &&
750                  Data.ExtraModifier <= OMPC_LINEAR_unknown &&
751                  "Unexpected linear modifier.");
752           if (P.getActions().CheckOpenMPLinearModifier(
753                   static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
754                   Data.ExtraModifierLoc))
755             Data.ExtraModifier = OMPC_LINEAR_val;
756           LinModifiers.append(Linears.size() - LinModifiers.size(),
757                               Data.ExtraModifier);
758           Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
759         }
760       } else
761         // TODO: add parsing of other clauses.
762         break;
763     }
764     // Skip ',' if any.
765     if (Tok.is(tok::comma))
766       P.ConsumeToken();
767   }
768   return IsError;
769 }
770 
771 /// Parse clauses for '#pragma omp declare simd'.
772 Parser::DeclGroupPtrTy
ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,CachedTokens & Toks,SourceLocation Loc)773 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
774                                    CachedTokens &Toks, SourceLocation Loc) {
775   PP.EnterToken(Tok, /*IsReinject*/ true);
776   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
777                       /*IsReinject*/ true);
778   // Consume the previously pushed token.
779   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
780   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
781 
782   FNContextRAII FnContext(*this, Ptr);
783   OMPDeclareSimdDeclAttr::BranchStateTy BS =
784       OMPDeclareSimdDeclAttr::BS_Undefined;
785   ExprResult Simdlen;
786   SmallVector<Expr *, 4> Uniforms;
787   SmallVector<Expr *, 4> Aligneds;
788   SmallVector<Expr *, 4> Alignments;
789   SmallVector<Expr *, 4> Linears;
790   SmallVector<unsigned, 4> LinModifiers;
791   SmallVector<Expr *, 4> Steps;
792   bool IsError =
793       parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
794                               Alignments, Linears, LinModifiers, Steps);
795   skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
796   // Skip the last annot_pragma_openmp_end.
797   SourceLocation EndLoc = ConsumeAnnotationToken();
798   if (IsError)
799     return Ptr;
800   return Actions.ActOnOpenMPDeclareSimdDirective(
801       Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
802       LinModifiers, Steps, SourceRange(Loc, EndLoc));
803 }
804 
805 namespace {
806 /// Constant used in the diagnostics to distinguish the levels in an OpenMP
807 /// contexts: selector-set={selector(trait, ...), ...}, ....
808 enum OMPContextLvl {
809   CONTEXT_SELECTOR_SET_LVL = 0,
810   CONTEXT_SELECTOR_LVL = 1,
811   CONTEXT_TRAIT_LVL = 2,
812 };
813 
stringLiteralParser(Parser & P)814 static StringRef stringLiteralParser(Parser &P) {
815   ExprResult Res = P.ParseStringLiteralExpression(true);
816   return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
817 }
818 
getNameFromIdOrString(Parser & P,Token & Tok,OMPContextLvl Lvl)819 static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
820                                        OMPContextLvl Lvl) {
821   if (Tok.is(tok::identifier)) {
822     llvm::SmallString<16> Buffer;
823     StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
824     (void)P.ConsumeToken();
825     return Name;
826   }
827 
828   if (tok::isStringLiteral(Tok.getKind()))
829     return stringLiteralParser(P);
830 
831   P.Diag(Tok.getLocation(),
832          diag::warn_omp_declare_variant_string_literal_or_identifier)
833       << Lvl;
834   return "";
835 }
836 
checkForDuplicates(Parser & P,StringRef Name,SourceLocation NameLoc,llvm::StringMap<SourceLocation> & Seen,OMPContextLvl Lvl)837 static bool checkForDuplicates(Parser &P, StringRef Name,
838                                SourceLocation NameLoc,
839                                llvm::StringMap<SourceLocation> &Seen,
840                                OMPContextLvl Lvl) {
841   auto Res = Seen.try_emplace(Name, NameLoc);
842   if (Res.second)
843     return false;
844 
845   // Each trait-set-selector-name, trait-selector-name and trait-name can
846   // only be specified once.
847   P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
848       << Lvl << Name;
849   P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
850       << Lvl << Name;
851   return true;
852 }
853 } // namespace
854 
parseOMPTraitPropertyKind(OMPTraitProperty & TIProperty,llvm::omp::TraitSet Set,llvm::omp::TraitSelector Selector,llvm::StringMap<SourceLocation> & Seen)855 void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
856                                        llvm::omp::TraitSet Set,
857                                        llvm::omp::TraitSelector Selector,
858                                        llvm::StringMap<SourceLocation> &Seen) {
859   TIProperty.Kind = TraitProperty::invalid;
860 
861   SourceLocation NameLoc = Tok.getLocation();
862   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
863   if (Name.empty()) {
864     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
865         << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
866     return;
867   }
868 
869   TIProperty.RawString = Name;
870   TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
871   if (TIProperty.Kind != TraitProperty::invalid) {
872     if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
873       TIProperty.Kind = TraitProperty::invalid;
874     return;
875   }
876 
877   // It follows diagnosis and helping notes.
878   // FIXME: We should move the diagnosis string generation into libFrontend.
879   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
880       << Name << getOpenMPContextTraitSelectorName(Selector)
881       << getOpenMPContextTraitSetName(Set);
882 
883   TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
884   if (SetForName != TraitSet::invalid) {
885     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
886         << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
887     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
888         << Name << "<selector-name>"
889         << "(<property-name>)";
890     return;
891   }
892   TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
893   if (SelectorForName != TraitSelector::invalid) {
894     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
895         << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
896     bool AllowsTraitScore = false;
897     bool RequiresProperty = false;
898     isValidTraitSelectorForTraitSet(
899         SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
900         AllowsTraitScore, RequiresProperty);
901     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
902         << getOpenMPContextTraitSetName(
903                getOpenMPContextTraitSetForSelector(SelectorForName))
904         << Name << (RequiresProperty ? "(<property-name>)" : "");
905     return;
906   }
907   for (const auto &PotentialSet :
908        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
909         TraitSet::device}) {
910     TraitProperty PropertyForName =
911         getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
912     if (PropertyForName == TraitProperty::invalid)
913       continue;
914     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
915         << getOpenMPContextTraitSetName(
916                getOpenMPContextTraitSetForProperty(PropertyForName))
917         << getOpenMPContextTraitSelectorName(
918                getOpenMPContextTraitSelectorForProperty(PropertyForName))
919         << ("(" + Name + ")").str();
920     return;
921   }
922   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
923       << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
924 }
925 
checkExtensionProperty(Parser & P,SourceLocation Loc,OMPTraitProperty & TIProperty,OMPTraitSelector & TISelector,llvm::StringMap<SourceLocation> & Seen)926 static bool checkExtensionProperty(Parser &P, SourceLocation Loc,
927                                    OMPTraitProperty &TIProperty,
928                                    OMPTraitSelector &TISelector,
929                                    llvm::StringMap<SourceLocation> &Seen) {
930   assert(TISelector.Kind ==
931              llvm::omp::TraitSelector::implementation_extension &&
932          "Only for extension properties, e.g., "
933          "`implementation={extension(PROPERTY)}`");
934   if (TIProperty.Kind == TraitProperty::invalid)
935     return false;
936 
937   if (TIProperty.Kind ==
938       TraitProperty::implementation_extension_disable_implicit_base)
939     return true;
940 
941   if (TIProperty.Kind ==
942       TraitProperty::implementation_extension_allow_templates)
943     return true;
944 
945   auto IsMatchExtension = [](OMPTraitProperty &TP) {
946     return (TP.Kind ==
947                 llvm::omp::TraitProperty::implementation_extension_match_all ||
948             TP.Kind ==
949                 llvm::omp::TraitProperty::implementation_extension_match_any ||
950             TP.Kind ==
951                 llvm::omp::TraitProperty::implementation_extension_match_none);
952   };
953 
954   if (IsMatchExtension(TIProperty)) {
955     for (OMPTraitProperty &SeenProp : TISelector.Properties)
956       if (IsMatchExtension(SeenProp)) {
957         P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
958         StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
959             SeenProp.Kind, SeenProp.RawString);
960         SourceLocation SeenLoc = Seen[SeenName];
961         P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
962             << CONTEXT_TRAIT_LVL << SeenName;
963         return false;
964       }
965     return true;
966   }
967 
968   llvm_unreachable("Unknown extension property!");
969 }
970 
parseOMPContextProperty(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & Seen)971 void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
972                                      llvm::omp::TraitSet Set,
973                                      llvm::StringMap<SourceLocation> &Seen) {
974   assert(TISelector.Kind != TraitSelector::user_condition &&
975          "User conditions are special properties not handled here!");
976 
977   SourceLocation PropertyLoc = Tok.getLocation();
978   OMPTraitProperty TIProperty;
979   parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
980 
981   if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
982     if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
983                                 TISelector, Seen))
984       TIProperty.Kind = TraitProperty::invalid;
985 
986   // If we have an invalid property here we already issued a warning.
987   if (TIProperty.Kind == TraitProperty::invalid) {
988     if (PropertyLoc != Tok.getLocation())
989       Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
990           << CONTEXT_TRAIT_LVL;
991     return;
992   }
993 
994   if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
995                                                  TISelector.Kind, Set)) {
996 
997     // If we make it here the property, selector, set, score, condition, ... are
998     // all valid (or have been corrected). Thus we can record the property.
999     TISelector.Properties.push_back(TIProperty);
1000     return;
1001   }
1002 
1003   Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
1004       << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1005                                            TIProperty.RawString)
1006       << getOpenMPContextTraitSelectorName(TISelector.Kind)
1007       << getOpenMPContextTraitSetName(Set);
1008   Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1009       << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1010                                            TIProperty.RawString)
1011       << getOpenMPContextTraitSelectorName(
1012              getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
1013       << getOpenMPContextTraitSetName(
1014              getOpenMPContextTraitSetForProperty(TIProperty.Kind));
1015   Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1016       << CONTEXT_TRAIT_LVL;
1017 }
1018 
parseOMPTraitSelectorKind(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & Seen)1019 void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
1020                                        llvm::omp::TraitSet Set,
1021                                        llvm::StringMap<SourceLocation> &Seen) {
1022   TISelector.Kind = TraitSelector::invalid;
1023 
1024   SourceLocation NameLoc = Tok.getLocation();
1025   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
1026   if (Name.empty()) {
1027     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1028         << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1029     return;
1030   }
1031 
1032   TISelector.Kind = getOpenMPContextTraitSelectorKind(Name);
1033   if (TISelector.Kind != TraitSelector::invalid) {
1034     if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1035       TISelector.Kind = TraitSelector::invalid;
1036     return;
1037   }
1038 
1039   // It follows diagnosis and helping notes.
1040   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1041       << Name << getOpenMPContextTraitSetName(Set);
1042 
1043   TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1044   if (SetForName != TraitSet::invalid) {
1045     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1046         << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1047     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1048         << Name << "<selector-name>"
1049         << "<property-name>";
1050     return;
1051   }
1052   for (const auto &PotentialSet :
1053        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1054         TraitSet::device}) {
1055     TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1056         PotentialSet, TraitSelector::invalid, Name);
1057     if (PropertyForName == TraitProperty::invalid)
1058       continue;
1059     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1060         << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1061     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1062         << getOpenMPContextTraitSetName(
1063                getOpenMPContextTraitSetForProperty(PropertyForName))
1064         << getOpenMPContextTraitSelectorName(
1065                getOpenMPContextTraitSelectorForProperty(PropertyForName))
1066         << ("(" + Name + ")").str();
1067     return;
1068   }
1069   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1070       << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1071 }
1072 
1073 /// Parse optional 'score' '(' <expr> ')' ':'.
parseContextScore(Parser & P)1074 static ExprResult parseContextScore(Parser &P) {
1075   ExprResult ScoreExpr;
1076   llvm::SmallString<16> Buffer;
1077   StringRef SelectorName =
1078       P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
1079   if (!SelectorName.equals("score"))
1080     return ScoreExpr;
1081   (void)P.ConsumeToken();
1082   SourceLocation RLoc;
1083   ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
1084   // Parse ':'
1085   if (P.getCurToken().is(tok::colon))
1086     (void)P.ConsumeAnyToken();
1087   else
1088     P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
1089         << "':'"
1090         << "score expression";
1091   return ScoreExpr;
1092 }
1093 
1094 /// Parses an OpenMP context selector.
1095 ///
1096 /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')']
parseOMPContextSelector(OMPTraitSelector & TISelector,llvm::omp::TraitSet Set,llvm::StringMap<SourceLocation> & SeenSelectors)1097 void Parser::parseOMPContextSelector(
1098     OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
1099     llvm::StringMap<SourceLocation> &SeenSelectors) {
1100   unsigned short OuterPC = ParenCount;
1101 
1102   // If anything went wrong we issue an error or warning and then skip the rest
1103   // of the selector. However, commas are ambiguous so we look for the nesting
1104   // of parentheses here as well.
1105   auto FinishSelector = [OuterPC, this]() -> void {
1106     bool Done = false;
1107     while (!Done) {
1108       while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1109                          tok::annot_pragma_openmp_end},
1110                         StopBeforeMatch))
1111         ;
1112       if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
1113         (void)ConsumeParen();
1114       if (OuterPC <= ParenCount) {
1115         Done = true;
1116         break;
1117       }
1118       if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
1119         Done = true;
1120         break;
1121       }
1122       (void)ConsumeAnyToken();
1123     }
1124     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1125         << CONTEXT_SELECTOR_LVL;
1126   };
1127 
1128   SourceLocation SelectorLoc = Tok.getLocation();
1129   parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
1130   if (TISelector.Kind == TraitSelector::invalid)
1131     return FinishSelector();
1132 
1133   bool AllowsTraitScore = false;
1134   bool RequiresProperty = false;
1135   if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
1136                                        RequiresProperty)) {
1137     Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1138         << getOpenMPContextTraitSelectorName(TISelector.Kind)
1139         << getOpenMPContextTraitSetName(Set);
1140     Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1141         << getOpenMPContextTraitSelectorName(TISelector.Kind)
1142         << getOpenMPContextTraitSetName(
1143                getOpenMPContextTraitSetForSelector(TISelector.Kind))
1144         << RequiresProperty;
1145     return FinishSelector();
1146   }
1147 
1148   if (!RequiresProperty) {
1149     TISelector.Properties.push_back(
1150         {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
1151          getOpenMPContextTraitSelectorName(TISelector.Kind)});
1152     return;
1153   }
1154 
1155   if (!Tok.is(tok::l_paren)) {
1156     Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1157         << getOpenMPContextTraitSelectorName(TISelector.Kind)
1158         << getOpenMPContextTraitSetName(Set);
1159     return FinishSelector();
1160   }
1161 
1162   if (TISelector.Kind == TraitSelector::user_condition) {
1163     SourceLocation RLoc;
1164     ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
1165     if (!Condition.isUsable())
1166       return FinishSelector();
1167     TISelector.ScoreOrCondition = Condition.get();
1168     TISelector.Properties.push_back(
1169         {TraitProperty::user_condition_unknown, "<condition>"});
1170     return;
1171   }
1172 
1173   BalancedDelimiterTracker BDT(*this, tok::l_paren,
1174                                tok::annot_pragma_openmp_end);
1175   // Parse '('.
1176   (void)BDT.consumeOpen();
1177 
1178   SourceLocation ScoreLoc = Tok.getLocation();
1179   ExprResult Score = parseContextScore(*this);
1180 
1181   if (!AllowsTraitScore && !Score.isUnset()) {
1182     if (Score.isUsable()) {
1183       Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1184           << getOpenMPContextTraitSelectorName(TISelector.Kind)
1185           << getOpenMPContextTraitSetName(Set) << Score.get();
1186     } else {
1187       Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1188           << getOpenMPContextTraitSelectorName(TISelector.Kind)
1189           << getOpenMPContextTraitSetName(Set) << "<invalid>";
1190     }
1191     Score = ExprResult();
1192   }
1193 
1194   if (Score.isUsable())
1195     TISelector.ScoreOrCondition = Score.get();
1196 
1197   llvm::StringMap<SourceLocation> SeenProperties;
1198   do {
1199     parseOMPContextProperty(TISelector, Set, SeenProperties);
1200   } while (TryConsumeToken(tok::comma));
1201 
1202   // Parse ')'.
1203   BDT.consumeClose();
1204 }
1205 
parseOMPTraitSetKind(OMPTraitSet & TISet,llvm::StringMap<SourceLocation> & Seen)1206 void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
1207                                   llvm::StringMap<SourceLocation> &Seen) {
1208   TISet.Kind = TraitSet::invalid;
1209 
1210   SourceLocation NameLoc = Tok.getLocation();
1211   StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
1212   if (Name.empty()) {
1213     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1214         << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1215     return;
1216   }
1217 
1218   TISet.Kind = getOpenMPContextTraitSetKind(Name);
1219   if (TISet.Kind != TraitSet::invalid) {
1220     if (checkForDuplicates(*this, Name, NameLoc, Seen,
1221                            CONTEXT_SELECTOR_SET_LVL))
1222       TISet.Kind = TraitSet::invalid;
1223     return;
1224   }
1225 
1226   // It follows diagnosis and helping notes.
1227   Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1228 
1229   TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
1230   if (SelectorForName != TraitSelector::invalid) {
1231     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1232         << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1233     bool AllowsTraitScore = false;
1234     bool RequiresProperty = false;
1235     isValidTraitSelectorForTraitSet(
1236         SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1237         AllowsTraitScore, RequiresProperty);
1238     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1239         << getOpenMPContextTraitSetName(
1240                getOpenMPContextTraitSetForSelector(SelectorForName))
1241         << Name << (RequiresProperty ? "(<property-name>)" : "");
1242     return;
1243   }
1244   for (const auto &PotentialSet :
1245        {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1246         TraitSet::device}) {
1247     TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1248         PotentialSet, TraitSelector::invalid, Name);
1249     if (PropertyForName == TraitProperty::invalid)
1250       continue;
1251     Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1252         << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1253     Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1254         << getOpenMPContextTraitSetName(
1255                getOpenMPContextTraitSetForProperty(PropertyForName))
1256         << getOpenMPContextTraitSelectorName(
1257                getOpenMPContextTraitSelectorForProperty(PropertyForName))
1258         << ("(" + Name + ")").str();
1259     return;
1260   }
1261   Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1262       << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1263 }
1264 
1265 /// Parses an OpenMP context selector set.
1266 ///
1267 /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}'
parseOMPContextSelectorSet(OMPTraitSet & TISet,llvm::StringMap<SourceLocation> & SeenSets)1268 void Parser::parseOMPContextSelectorSet(
1269     OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1270   auto OuterBC = BraceCount;
1271 
1272   // If anything went wrong we issue an error or warning and then skip the rest
1273   // of the set. However, commas are ambiguous so we look for the nesting
1274   // of braces here as well.
1275   auto FinishSelectorSet = [this, OuterBC]() -> void {
1276     bool Done = false;
1277     while (!Done) {
1278       while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1279                          tok::annot_pragma_openmp_end},
1280                         StopBeforeMatch))
1281         ;
1282       if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
1283         (void)ConsumeBrace();
1284       if (OuterBC <= BraceCount) {
1285         Done = true;
1286         break;
1287       }
1288       if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
1289         Done = true;
1290         break;
1291       }
1292       (void)ConsumeAnyToken();
1293     }
1294     Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1295         << CONTEXT_SELECTOR_SET_LVL;
1296   };
1297 
1298   parseOMPTraitSetKind(TISet, SeenSets);
1299   if (TISet.Kind == TraitSet::invalid)
1300     return FinishSelectorSet();
1301 
1302   // Parse '='.
1303   if (!TryConsumeToken(tok::equal))
1304     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1305         << "="
1306         << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
1307             "\"")
1308                .str();
1309 
1310   // Parse '{'.
1311   if (Tok.is(tok::l_brace)) {
1312     (void)ConsumeBrace();
1313   } else {
1314     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1315         << "{"
1316         << ("'=' that follows the context set name \"" +
1317             getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1318                .str();
1319   }
1320 
1321   llvm::StringMap<SourceLocation> SeenSelectors;
1322   do {
1323     OMPTraitSelector TISelector;
1324     parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
1325     if (TISelector.Kind != TraitSelector::invalid &&
1326         !TISelector.Properties.empty())
1327       TISet.Selectors.push_back(TISelector);
1328   } while (TryConsumeToken(tok::comma));
1329 
1330   // Parse '}'.
1331   if (Tok.is(tok::r_brace)) {
1332     (void)ConsumeBrace();
1333   } else {
1334     Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1335         << "}"
1336         << ("context selectors for the context set \"" +
1337             getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1338                .str();
1339   }
1340 }
1341 
1342 /// Parse OpenMP context selectors:
1343 ///
1344 /// <trait-set-selector> [, <trait-set-selector>]*
parseOMPContextSelectors(SourceLocation Loc,OMPTraitInfo & TI)1345 bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
1346   llvm::StringMap<SourceLocation> SeenSets;
1347   do {
1348     OMPTraitSet TISet;
1349     parseOMPContextSelectorSet(TISet, SeenSets);
1350     if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
1351       TI.Sets.push_back(TISet);
1352   } while (TryConsumeToken(tok::comma));
1353 
1354   return false;
1355 }
1356 
1357 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,CachedTokens & Toks,SourceLocation Loc)1358 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1359                                            CachedTokens &Toks,
1360                                            SourceLocation Loc) {
1361   PP.EnterToken(Tok, /*IsReinject*/ true);
1362   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1363                       /*IsReinject*/ true);
1364   // Consume the previously pushed token.
1365   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1366   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1367 
1368   FNContextRAII FnContext(*this, Ptr);
1369   // Parse function declaration id.
1370   SourceLocation RLoc;
1371   // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1372   // instead of MemberExprs.
1373   ExprResult AssociatedFunction;
1374   {
1375     // Do not mark function as is used to prevent its emission if this is the
1376     // only place where it is used.
1377     EnterExpressionEvaluationContext Unevaluated(
1378         Actions, Sema::ExpressionEvaluationContext::Unevaluated);
1379     AssociatedFunction = ParseOpenMPParensExpr(
1380         getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1381         /*IsAddressOfOperand=*/true);
1382   }
1383   if (!AssociatedFunction.isUsable()) {
1384     if (!Tok.is(tok::annot_pragma_openmp_end))
1385       while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1386         ;
1387     // Skip the last annot_pragma_openmp_end.
1388     (void)ConsumeAnnotationToken();
1389     return;
1390   }
1391 
1392   OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
1393   ASTContext &ASTCtx = Actions.getASTContext();
1394   OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1395   if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
1396     return;
1397 
1398   Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1399       Actions.checkOpenMPDeclareVariantFunction(
1400           Ptr, AssociatedFunction.get(), TI,
1401           SourceRange(Loc, Tok.getLocation()));
1402 
1403   // Skip last tokens.
1404   while (Tok.isNot(tok::annot_pragma_openmp_end))
1405     ConsumeAnyToken();
1406   if (DeclVarData && !TI.Sets.empty())
1407     Actions.ActOnOpenMPDeclareVariantDirective(
1408         DeclVarData->first, DeclVarData->second, TI,
1409         SourceRange(Loc, Tok.getLocation()));
1410 
1411   // Skip the last annot_pragma_openmp_end.
1412   (void)ConsumeAnnotationToken();
1413 }
1414 
parseOMPDeclareVariantMatchClause(SourceLocation Loc,OMPTraitInfo & TI,OMPTraitInfo * ParentTI)1415 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1416                                                OMPTraitInfo &TI,
1417                                                OMPTraitInfo *ParentTI) {
1418   // Parse 'match'.
1419   OpenMPClauseKind CKind = Tok.isAnnotation()
1420                                ? OMPC_unknown
1421                                : getOpenMPClauseKind(PP.getSpelling(Tok));
1422   if (CKind != OMPC_match) {
1423     Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1424         << getOpenMPClauseName(OMPC_match);
1425     while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
1426       ;
1427     // Skip the last annot_pragma_openmp_end.
1428     (void)ConsumeAnnotationToken();
1429     return true;
1430   }
1431   (void)ConsumeToken();
1432   // Parse '('.
1433   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1434   if (T.expectAndConsume(diag::err_expected_lparen_after,
1435                          getOpenMPClauseName(OMPC_match).data())) {
1436     while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1437       ;
1438     // Skip the last annot_pragma_openmp_end.
1439     (void)ConsumeAnnotationToken();
1440     return true;
1441   }
1442 
1443   // Parse inner context selectors.
1444   parseOMPContextSelectors(Loc, TI);
1445 
1446   // Parse ')'
1447   (void)T.consumeClose();
1448 
1449   if (!ParentTI)
1450     return false;
1451 
1452   // Merge the parent/outer trait info into the one we just parsed and diagnose
1453   // problems.
1454   // TODO: Keep some source location in the TI to provide better diagnostics.
1455   // TODO: Perform some kind of equivalence check on the condition and score
1456   //       expressions.
1457   for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
1458     bool MergedSet = false;
1459     for (OMPTraitSet &Set : TI.Sets) {
1460       if (Set.Kind != ParentSet.Kind)
1461         continue;
1462       MergedSet = true;
1463       for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
1464         bool MergedSelector = false;
1465         for (OMPTraitSelector &Selector : Set.Selectors) {
1466           if (Selector.Kind != ParentSelector.Kind)
1467             continue;
1468           MergedSelector = true;
1469           for (const OMPTraitProperty &ParentProperty :
1470                ParentSelector.Properties) {
1471             bool MergedProperty = false;
1472             for (OMPTraitProperty &Property : Selector.Properties) {
1473               // Ignore "equivalent" properties.
1474               if (Property.Kind != ParentProperty.Kind)
1475                 continue;
1476 
1477               // If the kind is the same but the raw string not, we don't want
1478               // to skip out on the property.
1479               MergedProperty |= Property.RawString == ParentProperty.RawString;
1480 
1481               if (Property.RawString == ParentProperty.RawString &&
1482                   Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
1483                 continue;
1484 
1485               if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1486                 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1487               } else if (Selector.ScoreOrCondition !=
1488                          ParentSelector.ScoreOrCondition) {
1489                 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1490                     << getOpenMPContextTraitPropertyName(
1491                            ParentProperty.Kind, ParentProperty.RawString)
1492                     << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
1493                     << getOpenMPContextTraitSetName(ParentSet.Kind);
1494               }
1495             }
1496             if (!MergedProperty)
1497               Selector.Properties.push_back(ParentProperty);
1498           }
1499         }
1500         if (!MergedSelector)
1501           Set.Selectors.push_back(ParentSelector);
1502       }
1503     }
1504     if (!MergedSet)
1505       TI.Sets.push_back(ParentSet);
1506   }
1507 
1508   return false;
1509 }
1510 
1511 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1512 ///
1513 ///    default-clause:
1514 ///         'default' '(' 'none' | 'shared'  | 'firstprivate' ')
1515 ///
1516 ///    proc_bind-clause:
1517 ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
1518 ///
1519 ///    device_type-clause:
1520 ///         'device_type' '(' 'host' | 'nohost' | 'any' )'
1521 namespace {
1522 struct SimpleClauseData {
1523   unsigned Type;
1524   SourceLocation Loc;
1525   SourceLocation LOpen;
1526   SourceLocation TypeLoc;
1527   SourceLocation RLoc;
SimpleClauseData__anon755a15050a11::SimpleClauseData1528   SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1529                    SourceLocation TypeLoc, SourceLocation RLoc)
1530       : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1531 };
1532 } // anonymous namespace
1533 
1534 static Optional<SimpleClauseData>
parseOpenMPSimpleClause(Parser & P,OpenMPClauseKind Kind)1535 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
1536   const Token &Tok = P.getCurToken();
1537   SourceLocation Loc = Tok.getLocation();
1538   SourceLocation LOpen = P.ConsumeToken();
1539   // Parse '('.
1540   BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1541   if (T.expectAndConsume(diag::err_expected_lparen_after,
1542                          getOpenMPClauseName(Kind).data()))
1543     return llvm::None;
1544 
1545   unsigned Type = getOpenMPSimpleClauseType(
1546       Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
1547       P.getLangOpts().OpenMP);
1548   SourceLocation TypeLoc = Tok.getLocation();
1549   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1550       Tok.isNot(tok::annot_pragma_openmp_end))
1551     P.ConsumeAnyToken();
1552 
1553   // Parse ')'.
1554   SourceLocation RLoc = Tok.getLocation();
1555   if (!T.consumeClose())
1556     RLoc = T.getCloseLocation();
1557 
1558   return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1559 }
1560 
ParseOMPDeclareTargetClauses()1561 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
1562   // OpenMP 4.5 syntax with list of entities.
1563   Sema::NamedDeclSetType SameDirectiveDecls;
1564   SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation,
1565                          NamedDecl *>,
1566               4>
1567       DeclareTargetDecls;
1568   OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
1569   SourceLocation DeviceTypeLoc;
1570   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1571     OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1572     if (Tok.is(tok::identifier)) {
1573       IdentifierInfo *II = Tok.getIdentifierInfo();
1574       StringRef ClauseName = II->getName();
1575       bool IsDeviceTypeClause =
1576           getLangOpts().OpenMP >= 50 &&
1577           getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1578       // Parse 'to|link|device_type' clauses.
1579       if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
1580           !IsDeviceTypeClause) {
1581         Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1582             << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
1583         break;
1584       }
1585       // Parse 'device_type' clause and go to next clause if any.
1586       if (IsDeviceTypeClause) {
1587         Optional<SimpleClauseData> DevTypeData =
1588             parseOpenMPSimpleClause(*this, OMPC_device_type);
1589         if (DevTypeData.hasValue()) {
1590           if (DeviceTypeLoc.isValid()) {
1591             // We already saw another device_type clause, diagnose it.
1592             Diag(DevTypeData.getValue().Loc,
1593                  diag::warn_omp_more_one_device_type_clause);
1594           }
1595           switch (static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
1596           case OMPC_DEVICE_TYPE_any:
1597             DT = OMPDeclareTargetDeclAttr::DT_Any;
1598             break;
1599           case OMPC_DEVICE_TYPE_host:
1600             DT = OMPDeclareTargetDeclAttr::DT_Host;
1601             break;
1602           case OMPC_DEVICE_TYPE_nohost:
1603             DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1604             break;
1605           case OMPC_DEVICE_TYPE_unknown:
1606             llvm_unreachable("Unexpected device_type");
1607           }
1608           DeviceTypeLoc = DevTypeData.getValue().Loc;
1609         }
1610         continue;
1611       }
1612       ConsumeToken();
1613     }
1614     auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
1615                           CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
1616       NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
1617           getCurScope(), SS, NameInfo, SameDirectiveDecls);
1618       if (ND)
1619         DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
1620     };
1621     if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1622                                  /*AllowScopeSpecifier=*/true))
1623       break;
1624 
1625     // Consume optional ','.
1626     if (Tok.is(tok::comma))
1627       ConsumeToken();
1628   }
1629   SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1630   ConsumeAnyToken();
1631   for (auto &MTLocDecl : DeclareTargetDecls) {
1632     OMPDeclareTargetDeclAttr::MapTypeTy MT;
1633     SourceLocation Loc;
1634     NamedDecl *ND;
1635     std::tie(MT, Loc, ND) = MTLocDecl;
1636     // device_type clause is applied only to functions.
1637     Actions.ActOnOpenMPDeclareTargetName(
1638         ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
1639   }
1640   SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
1641                                SameDirectiveDecls.end());
1642   if (Decls.empty())
1643     return DeclGroupPtrTy();
1644   return Actions.BuildDeclaratorGroup(Decls);
1645 }
1646 
skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind)1647 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1648   // The last seen token is annot_pragma_openmp_end - need to check for
1649   // extra tokens.
1650   if (Tok.is(tok::annot_pragma_openmp_end))
1651     return;
1652 
1653   Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1654       << getOpenMPDirectiveName(DKind);
1655   while (Tok.isNot(tok::annot_pragma_openmp_end))
1656     ConsumeAnyToken();
1657 }
1658 
parseOMPEndDirective(OpenMPDirectiveKind BeginKind,OpenMPDirectiveKind ExpectedKind,OpenMPDirectiveKind FoundKind,SourceLocation BeginLoc,SourceLocation FoundLoc,bool SkipUntilOpenMPEnd)1659 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1660                                   OpenMPDirectiveKind ExpectedKind,
1661                                   OpenMPDirectiveKind FoundKind,
1662                                   SourceLocation BeginLoc,
1663                                   SourceLocation FoundLoc,
1664                                   bool SkipUntilOpenMPEnd) {
1665   int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1666 
1667   if (FoundKind == ExpectedKind) {
1668     ConsumeAnyToken();
1669     skipUntilPragmaOpenMPEnd(ExpectedKind);
1670     return;
1671   }
1672 
1673   Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1674       << DiagSelection;
1675   Diag(BeginLoc, diag::note_matching)
1676       << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
1677   if (SkipUntilOpenMPEnd)
1678     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1679 }
1680 
ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,SourceLocation DKLoc)1681 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
1682                                                SourceLocation DKLoc) {
1683   parseOMPEndDirective(OMPD_declare_target, OMPD_end_declare_target, DKind,
1684                        DKLoc, Tok.getLocation(),
1685                        /* SkipUntilOpenMPEnd */ false);
1686   // Skip the last annot_pragma_openmp_end.
1687   if (Tok.is(tok::annot_pragma_openmp_end))
1688     ConsumeAnnotationToken();
1689 }
1690 
1691 /// Parsing of declarative OpenMP directives.
1692 ///
1693 ///       threadprivate-directive:
1694 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
1695 ///         annot_pragma_openmp_end
1696 ///
1697 ///       allocate-directive:
1698 ///         annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
1699 ///         annot_pragma_openmp_end
1700 ///
1701 ///       declare-reduction-directive:
1702 ///        annot_pragma_openmp 'declare' 'reduction' [...]
1703 ///        annot_pragma_openmp_end
1704 ///
1705 ///       declare-mapper-directive:
1706 ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1707 ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
1708 ///         annot_pragma_openmp_end
1709 ///
1710 ///       declare-simd-directive:
1711 ///         annot_pragma_openmp 'declare simd' {<clause> [,]}
1712 ///         annot_pragma_openmp_end
1713 ///         <function declaration/definition>
1714 ///
1715 ///       requires directive:
1716 ///         annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
1717 ///         annot_pragma_openmp_end
1718 ///
ParseOpenMPDeclarativeDirectiveWithExtDecl(AccessSpecifier & AS,ParsedAttributesWithRange & Attrs,bool Delayed,DeclSpec::TST TagType,Decl * Tag)1719 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
1720     AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
1721     DeclSpec::TST TagType, Decl *Tag) {
1722   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1723   ParsingOpenMPDirectiveRAII DirScope(*this);
1724   ParenBraceBracketBalancer BalancerRAIIObj(*this);
1725 
1726   SourceLocation Loc;
1727   OpenMPDirectiveKind DKind;
1728   if (Delayed) {
1729     TentativeParsingAction TPA(*this);
1730     Loc = ConsumeAnnotationToken();
1731     DKind = parseOpenMPDirectiveKind(*this);
1732     if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1733       // Need to delay parsing until completion of the parent class.
1734       TPA.Revert();
1735       CachedTokens Toks;
1736       unsigned Cnt = 1;
1737       Toks.push_back(Tok);
1738       while (Cnt && Tok.isNot(tok::eof)) {
1739         (void)ConsumeAnyToken();
1740         if (Tok.is(tok::annot_pragma_openmp))
1741           ++Cnt;
1742         else if (Tok.is(tok::annot_pragma_openmp_end))
1743           --Cnt;
1744         Toks.push_back(Tok);
1745       }
1746       // Skip last annot_pragma_openmp_end.
1747       if (Cnt == 0)
1748         (void)ConsumeAnyToken();
1749       auto *LP = new LateParsedPragma(this, AS);
1750       LP->takeToks(Toks);
1751       getCurrentClass().LateParsedDeclarations.push_back(LP);
1752       return nullptr;
1753     }
1754     TPA.Commit();
1755   } else {
1756     Loc = ConsumeAnnotationToken();
1757     DKind = parseOpenMPDirectiveKind(*this);
1758   }
1759 
1760   switch (DKind) {
1761   case OMPD_threadprivate: {
1762     ConsumeToken();
1763     DeclDirectiveListParserHelper Helper(this, DKind);
1764     if (!ParseOpenMPSimpleVarList(DKind, Helper,
1765                                   /*AllowScopeSpecifier=*/true)) {
1766       skipUntilPragmaOpenMPEnd(DKind);
1767       // Skip the last annot_pragma_openmp_end.
1768       ConsumeAnnotationToken();
1769       return Actions.ActOnOpenMPThreadprivateDirective(Loc,
1770                                                        Helper.getIdentifiers());
1771     }
1772     break;
1773   }
1774   case OMPD_allocate: {
1775     ConsumeToken();
1776     DeclDirectiveListParserHelper Helper(this, DKind);
1777     if (!ParseOpenMPSimpleVarList(DKind, Helper,
1778                                   /*AllowScopeSpecifier=*/true)) {
1779       SmallVector<OMPClause *, 1> Clauses;
1780       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1781         SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1782                     llvm::omp::Clause_enumSize + 1>
1783             FirstClauses(llvm::omp::Clause_enumSize + 1);
1784         while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1785           OpenMPClauseKind CKind =
1786               Tok.isAnnotation() ? OMPC_unknown
1787                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
1788           Actions.StartOpenMPClause(CKind);
1789           OMPClause *Clause = ParseOpenMPClause(
1790               OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt());
1791           SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1792                     StopBeforeMatch);
1793           FirstClauses[unsigned(CKind)].setInt(true);
1794           if (Clause != nullptr)
1795             Clauses.push_back(Clause);
1796           if (Tok.is(tok::annot_pragma_openmp_end)) {
1797             Actions.EndOpenMPClause();
1798             break;
1799           }
1800           // Skip ',' if any.
1801           if (Tok.is(tok::comma))
1802             ConsumeToken();
1803           Actions.EndOpenMPClause();
1804         }
1805         skipUntilPragmaOpenMPEnd(DKind);
1806       }
1807       // Skip the last annot_pragma_openmp_end.
1808       ConsumeAnnotationToken();
1809       return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
1810                                                   Clauses);
1811     }
1812     break;
1813   }
1814   case OMPD_requires: {
1815     SourceLocation StartLoc = ConsumeToken();
1816     SmallVector<OMPClause *, 5> Clauses;
1817     SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1818                 llvm::omp::Clause_enumSize + 1>
1819         FirstClauses(llvm::omp::Clause_enumSize + 1);
1820     if (Tok.is(tok::annot_pragma_openmp_end)) {
1821       Diag(Tok, diag::err_omp_expected_clause)
1822           << getOpenMPDirectiveName(OMPD_requires);
1823       break;
1824     }
1825     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1826       OpenMPClauseKind CKind = Tok.isAnnotation()
1827                                    ? OMPC_unknown
1828                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
1829       Actions.StartOpenMPClause(CKind);
1830       OMPClause *Clause = ParseOpenMPClause(
1831           OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt());
1832       SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1833                 StopBeforeMatch);
1834       FirstClauses[unsigned(CKind)].setInt(true);
1835       if (Clause != nullptr)
1836         Clauses.push_back(Clause);
1837       if (Tok.is(tok::annot_pragma_openmp_end)) {
1838         Actions.EndOpenMPClause();
1839         break;
1840       }
1841       // Skip ',' if any.
1842       if (Tok.is(tok::comma))
1843         ConsumeToken();
1844       Actions.EndOpenMPClause();
1845     }
1846     // Consume final annot_pragma_openmp_end
1847     if (Clauses.empty()) {
1848       Diag(Tok, diag::err_omp_expected_clause)
1849           << getOpenMPDirectiveName(OMPD_requires);
1850       ConsumeAnnotationToken();
1851       return nullptr;
1852     }
1853     ConsumeAnnotationToken();
1854     return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
1855   }
1856   case OMPD_declare_reduction:
1857     ConsumeToken();
1858     if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
1859       skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
1860       // Skip the last annot_pragma_openmp_end.
1861       ConsumeAnnotationToken();
1862       return Res;
1863     }
1864     break;
1865   case OMPD_declare_mapper: {
1866     ConsumeToken();
1867     if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
1868       // Skip the last annot_pragma_openmp_end.
1869       ConsumeAnnotationToken();
1870       return Res;
1871     }
1872     break;
1873   }
1874   case OMPD_begin_declare_variant: {
1875     // The syntax is:
1876     // { #pragma omp begin declare variant clause }
1877     // <function-declaration-or-definition-sequence>
1878     // { #pragma omp end declare variant }
1879     //
1880     ConsumeToken();
1881     OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
1882     ASTContext &ASTCtx = Actions.getASTContext();
1883     OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1884     if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
1885       break;
1886 
1887     // Skip last tokens.
1888     skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
1889 
1890     ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
1891 
1892     VariantMatchInfo VMI;
1893     TI.getAsVariantMatchInfo(ASTCtx, VMI);
1894 
1895     std::function<void(StringRef)> DiagUnknownTrait = [this, Loc](
1896                                                           StringRef ISATrait) {
1897       // TODO Track the selector locations in a way that is accessible here to
1898       // improve the diagnostic location.
1899       Diag(Loc, diag::warn_unknown_begin_declare_variant_isa_trait) << ISATrait;
1900     };
1901     TargetOMPContext OMPCtx(ASTCtx, std::move(DiagUnknownTrait),
1902                             /* CurrentFunctionDecl */ nullptr);
1903 
1904     if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
1905       Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI);
1906       break;
1907     }
1908 
1909     // Elide all the code till the matching end declare variant was found.
1910     unsigned Nesting = 1;
1911     SourceLocation DKLoc;
1912     OpenMPDirectiveKind DK = OMPD_unknown;
1913     do {
1914       DKLoc = Tok.getLocation();
1915       DK = parseOpenMPDirectiveKind(*this);
1916       if (DK == OMPD_end_declare_variant)
1917         --Nesting;
1918       else if (DK == OMPD_begin_declare_variant)
1919         ++Nesting;
1920       if (!Nesting || isEofOrEom())
1921         break;
1922       ConsumeAnyToken();
1923     } while (true);
1924 
1925     parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
1926                          DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
1927     if (isEofOrEom())
1928       return nullptr;
1929     break;
1930   }
1931   case OMPD_end_declare_variant: {
1932     if (Actions.isInOpenMPDeclareVariantScope())
1933       Actions.ActOnOpenMPEndDeclareVariant();
1934     else
1935       Diag(Loc, diag::err_expected_begin_declare_variant);
1936     ConsumeToken();
1937     break;
1938   }
1939   case OMPD_declare_variant:
1940   case OMPD_declare_simd: {
1941     // The syntax is:
1942     // { #pragma omp declare {simd|variant} }
1943     // <function-declaration-or-definition>
1944     //
1945     CachedTokens Toks;
1946     Toks.push_back(Tok);
1947     ConsumeToken();
1948     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1949       Toks.push_back(Tok);
1950       ConsumeAnyToken();
1951     }
1952     Toks.push_back(Tok);
1953     ConsumeAnyToken();
1954 
1955     DeclGroupPtrTy Ptr;
1956     if (Tok.is(tok::annot_pragma_openmp)) {
1957       Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
1958                                                        TagType, Tag);
1959     } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1960       // Here we expect to see some function declaration.
1961       if (AS == AS_none) {
1962         assert(TagType == DeclSpec::TST_unspecified);
1963         MaybeParseCXX11Attributes(Attrs);
1964         ParsingDeclSpec PDS(*this);
1965         Ptr = ParseExternalDeclaration(Attrs, &PDS);
1966       } else {
1967         Ptr =
1968             ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1969       }
1970     }
1971     if (!Ptr) {
1972       Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
1973           << (DKind == OMPD_declare_simd ? 0 : 1);
1974       return DeclGroupPtrTy();
1975     }
1976     if (DKind == OMPD_declare_simd)
1977       return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
1978     assert(DKind == OMPD_declare_variant &&
1979            "Expected declare variant directive only");
1980     ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
1981     return Ptr;
1982   }
1983   case OMPD_declare_target: {
1984     SourceLocation DTLoc = ConsumeAnyToken();
1985     if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1986       return ParseOMPDeclareTargetClauses();
1987     }
1988 
1989     // Skip the last annot_pragma_openmp_end.
1990     ConsumeAnyToken();
1991 
1992     if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1993       return DeclGroupPtrTy();
1994 
1995     ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
1996     llvm::SmallVector<Decl *, 4> Decls;
1997     DKind = parseOpenMPDirectiveKind(*this);
1998     while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
1999            Tok.isNot(tok::r_brace)) {
2000       DeclGroupPtrTy Ptr;
2001       // Here we expect to see some function declaration.
2002       if (AS == AS_none) {
2003         assert(TagType == DeclSpec::TST_unspecified);
2004         MaybeParseCXX11Attributes(Attrs);
2005         ParsingDeclSpec PDS(*this);
2006         Ptr = ParseExternalDeclaration(Attrs, &PDS);
2007       } else {
2008         Ptr =
2009             ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
2010       }
2011       if (Ptr) {
2012         DeclGroupRef Ref = Ptr.get();
2013         Decls.append(Ref.begin(), Ref.end());
2014       }
2015       if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
2016         TentativeParsingAction TPA(*this);
2017         ConsumeAnnotationToken();
2018         DKind = parseOpenMPDirectiveKind(*this);
2019         if (DKind != OMPD_end_declare_target)
2020           TPA.Revert();
2021         else
2022           TPA.Commit();
2023       }
2024     }
2025 
2026     ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
2027     Actions.ActOnFinishOpenMPDeclareTargetDirective();
2028     return Actions.BuildDeclaratorGroup(Decls);
2029   }
2030   case OMPD_unknown:
2031     Diag(Tok, diag::err_omp_unknown_directive);
2032     break;
2033   case OMPD_parallel:
2034   case OMPD_simd:
2035   case OMPD_task:
2036   case OMPD_taskyield:
2037   case OMPD_barrier:
2038   case OMPD_taskwait:
2039   case OMPD_taskgroup:
2040   case OMPD_flush:
2041   case OMPD_depobj:
2042   case OMPD_scan:
2043   case OMPD_for:
2044   case OMPD_for_simd:
2045   case OMPD_sections:
2046   case OMPD_section:
2047   case OMPD_single:
2048   case OMPD_master:
2049   case OMPD_ordered:
2050   case OMPD_critical:
2051   case OMPD_parallel_for:
2052   case OMPD_parallel_for_simd:
2053   case OMPD_parallel_sections:
2054   case OMPD_parallel_master:
2055   case OMPD_atomic:
2056   case OMPD_target:
2057   case OMPD_teams:
2058   case OMPD_cancellation_point:
2059   case OMPD_cancel:
2060   case OMPD_target_data:
2061   case OMPD_target_enter_data:
2062   case OMPD_target_exit_data:
2063   case OMPD_target_parallel:
2064   case OMPD_target_parallel_for:
2065   case OMPD_taskloop:
2066   case OMPD_taskloop_simd:
2067   case OMPD_master_taskloop:
2068   case OMPD_master_taskloop_simd:
2069   case OMPD_parallel_master_taskloop:
2070   case OMPD_parallel_master_taskloop_simd:
2071   case OMPD_distribute:
2072   case OMPD_end_declare_target:
2073   case OMPD_target_update:
2074   case OMPD_distribute_parallel_for:
2075   case OMPD_distribute_parallel_for_simd:
2076   case OMPD_distribute_simd:
2077   case OMPD_target_parallel_for_simd:
2078   case OMPD_target_simd:
2079   case OMPD_teams_distribute:
2080   case OMPD_teams_distribute_simd:
2081   case OMPD_teams_distribute_parallel_for_simd:
2082   case OMPD_teams_distribute_parallel_for:
2083   case OMPD_target_teams:
2084   case OMPD_target_teams_distribute:
2085   case OMPD_target_teams_distribute_parallel_for:
2086   case OMPD_target_teams_distribute_parallel_for_simd:
2087   case OMPD_target_teams_distribute_simd:
2088     Diag(Tok, diag::err_omp_unexpected_directive)
2089         << 1 << getOpenMPDirectiveName(DKind);
2090     break;
2091   default:
2092     break;
2093   }
2094   while (Tok.isNot(tok::annot_pragma_openmp_end))
2095     ConsumeAnyToken();
2096   ConsumeAnyToken();
2097   return nullptr;
2098 }
2099 
2100 /// Parsing of declarative or executable OpenMP directives.
2101 ///
2102 ///       threadprivate-directive:
2103 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
2104 ///         annot_pragma_openmp_end
2105 ///
2106 ///       allocate-directive:
2107 ///         annot_pragma_openmp 'allocate' simple-variable-list
2108 ///         annot_pragma_openmp_end
2109 ///
2110 ///       declare-reduction-directive:
2111 ///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
2112 ///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
2113 ///         ('omp_priv' '=' <expression>|<function_call>) ')']
2114 ///         annot_pragma_openmp_end
2115 ///
2116 ///       declare-mapper-directive:
2117 ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
2118 ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
2119 ///         annot_pragma_openmp_end
2120 ///
2121 ///       executable-directive:
2122 ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
2123 ///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
2124 ///         'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
2125 ///         'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' |
2126 ///         'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
2127 ///         data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
2128 ///         'master taskloop' | 'master taskloop simd' | 'parallel master
2129 ///         taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
2130 ///         enter data' | 'target exit data' | 'target parallel' | 'target
2131 ///         parallel for' | 'target update' | 'distribute parallel for' |
2132 ///         'distribute paralle for simd' | 'distribute simd' | 'target parallel
2133 ///         for simd' | 'target simd' | 'teams distribute' | 'teams distribute
2134 ///         simd' | 'teams distribute parallel for simd' | 'teams distribute
2135 ///         parallel for' | 'target teams' | 'target teams distribute' | 'target
2136 ///         teams distribute parallel for' | 'target teams distribute parallel
2137 ///         for simd' | 'target teams distribute simd' {clause}
2138 ///         annot_pragma_openmp_end
2139 ///
2140 StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx)2141 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
2142   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
2143   ParsingOpenMPDirectiveRAII DirScope(*this);
2144   ParenBraceBracketBalancer BalancerRAIIObj(*this);
2145   SmallVector<OMPClause *, 5> Clauses;
2146   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
2147               llvm::omp::Clause_enumSize + 1>
2148       FirstClauses(llvm::omp::Clause_enumSize + 1);
2149   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2150                         Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
2151   SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
2152   OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
2153   OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2154   // Name of critical directive.
2155   DeclarationNameInfo DirName;
2156   StmtResult Directive = StmtError();
2157   bool HasAssociatedStatement = true;
2158 
2159   switch (DKind) {
2160   case OMPD_threadprivate: {
2161     // FIXME: Should this be permitted in C++?
2162     if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
2163         ParsedStmtContext()) {
2164       Diag(Tok, diag::err_omp_immediate_directive)
2165           << getOpenMPDirectiveName(DKind) << 0;
2166     }
2167     ConsumeToken();
2168     DeclDirectiveListParserHelper Helper(this, DKind);
2169     if (!ParseOpenMPSimpleVarList(DKind, Helper,
2170                                   /*AllowScopeSpecifier=*/false)) {
2171       skipUntilPragmaOpenMPEnd(DKind);
2172       DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
2173           Loc, Helper.getIdentifiers());
2174       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2175     }
2176     SkipUntil(tok::annot_pragma_openmp_end);
2177     break;
2178   }
2179   case OMPD_allocate: {
2180     // FIXME: Should this be permitted in C++?
2181     if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
2182         ParsedStmtContext()) {
2183       Diag(Tok, diag::err_omp_immediate_directive)
2184           << getOpenMPDirectiveName(DKind) << 0;
2185     }
2186     ConsumeToken();
2187     DeclDirectiveListParserHelper Helper(this, DKind);
2188     if (!ParseOpenMPSimpleVarList(DKind, Helper,
2189                                   /*AllowScopeSpecifier=*/false)) {
2190       SmallVector<OMPClause *, 1> Clauses;
2191       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2192         SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
2193                     llvm::omp::Clause_enumSize + 1>
2194             FirstClauses(llvm::omp::Clause_enumSize + 1);
2195         while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2196           OpenMPClauseKind CKind =
2197               Tok.isAnnotation() ? OMPC_unknown
2198                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
2199           Actions.StartOpenMPClause(CKind);
2200           OMPClause *Clause = ParseOpenMPClause(
2201               OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt());
2202           SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2203                     StopBeforeMatch);
2204           FirstClauses[unsigned(CKind)].setInt(true);
2205           if (Clause != nullptr)
2206             Clauses.push_back(Clause);
2207           if (Tok.is(tok::annot_pragma_openmp_end)) {
2208             Actions.EndOpenMPClause();
2209             break;
2210           }
2211           // Skip ',' if any.
2212           if (Tok.is(tok::comma))
2213             ConsumeToken();
2214           Actions.EndOpenMPClause();
2215         }
2216         skipUntilPragmaOpenMPEnd(DKind);
2217       }
2218       DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
2219           Loc, Helper.getIdentifiers(), Clauses);
2220       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2221     }
2222     SkipUntil(tok::annot_pragma_openmp_end);
2223     break;
2224   }
2225   case OMPD_declare_reduction:
2226     ConsumeToken();
2227     if (DeclGroupPtrTy Res =
2228             ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2229       skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2230       ConsumeAnyToken();
2231       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2232     } else {
2233       SkipUntil(tok::annot_pragma_openmp_end);
2234     }
2235     break;
2236   case OMPD_declare_mapper: {
2237     ConsumeToken();
2238     if (DeclGroupPtrTy Res =
2239             ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2240       // Skip the last annot_pragma_openmp_end.
2241       ConsumeAnnotationToken();
2242       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2243     } else {
2244       SkipUntil(tok::annot_pragma_openmp_end);
2245     }
2246     break;
2247   }
2248   case OMPD_flush:
2249   case OMPD_depobj:
2250   case OMPD_scan:
2251   case OMPD_taskyield:
2252   case OMPD_barrier:
2253   case OMPD_taskwait:
2254   case OMPD_cancellation_point:
2255   case OMPD_cancel:
2256   case OMPD_target_enter_data:
2257   case OMPD_target_exit_data:
2258   case OMPD_target_update:
2259     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2260         ParsedStmtContext()) {
2261       Diag(Tok, diag::err_omp_immediate_directive)
2262           << getOpenMPDirectiveName(DKind) << 0;
2263     }
2264     HasAssociatedStatement = false;
2265     // Fall through for further analysis.
2266     LLVM_FALLTHROUGH;
2267   case OMPD_parallel:
2268   case OMPD_simd:
2269   case OMPD_for:
2270   case OMPD_for_simd:
2271   case OMPD_sections:
2272   case OMPD_single:
2273   case OMPD_section:
2274   case OMPD_master:
2275   case OMPD_critical:
2276   case OMPD_parallel_for:
2277   case OMPD_parallel_for_simd:
2278   case OMPD_parallel_sections:
2279   case OMPD_parallel_master:
2280   case OMPD_task:
2281   case OMPD_ordered:
2282   case OMPD_atomic:
2283   case OMPD_target:
2284   case OMPD_teams:
2285   case OMPD_taskgroup:
2286   case OMPD_target_data:
2287   case OMPD_target_parallel:
2288   case OMPD_target_parallel_for:
2289   case OMPD_taskloop:
2290   case OMPD_taskloop_simd:
2291   case OMPD_master_taskloop:
2292   case OMPD_master_taskloop_simd:
2293   case OMPD_parallel_master_taskloop:
2294   case OMPD_parallel_master_taskloop_simd:
2295   case OMPD_distribute:
2296   case OMPD_distribute_parallel_for:
2297   case OMPD_distribute_parallel_for_simd:
2298   case OMPD_distribute_simd:
2299   case OMPD_target_parallel_for_simd:
2300   case OMPD_target_simd:
2301   case OMPD_teams_distribute:
2302   case OMPD_teams_distribute_simd:
2303   case OMPD_teams_distribute_parallel_for_simd:
2304   case OMPD_teams_distribute_parallel_for:
2305   case OMPD_target_teams:
2306   case OMPD_target_teams_distribute:
2307   case OMPD_target_teams_distribute_parallel_for:
2308   case OMPD_target_teams_distribute_parallel_for_simd:
2309   case OMPD_target_teams_distribute_simd: {
2310     // Special processing for flush and depobj clauses.
2311     Token ImplicitTok;
2312     bool ImplicitClauseAllowed = false;
2313     if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2314       ImplicitTok = Tok;
2315       ImplicitClauseAllowed = true;
2316     }
2317     ConsumeToken();
2318     // Parse directive name of the 'critical' directive if any.
2319     if (DKind == OMPD_critical) {
2320       BalancedDelimiterTracker T(*this, tok::l_paren,
2321                                  tok::annot_pragma_openmp_end);
2322       if (!T.consumeOpen()) {
2323         if (Tok.isAnyIdentifier()) {
2324           DirName =
2325               DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2326           ConsumeAnyToken();
2327         } else {
2328           Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2329         }
2330         T.consumeClose();
2331       }
2332     } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2333       CancelRegion = parseOpenMPDirectiveKind(*this);
2334       if (Tok.isNot(tok::annot_pragma_openmp_end))
2335         ConsumeToken();
2336     }
2337 
2338     if (isOpenMPLoopDirective(DKind))
2339       ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2340     if (isOpenMPSimdDirective(DKind))
2341       ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2342     ParseScope OMPDirectiveScope(this, ScopeFlags);
2343     Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
2344 
2345     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2346       bool HasImplicitClause = false;
2347       if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2348         HasImplicitClause = true;
2349         // Push copy of the current token back to stream to properly parse
2350         // pseudo-clause OMPFlushClause or OMPDepobjClause.
2351         PP.EnterToken(Tok, /*IsReinject*/ true);
2352         PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2353         ConsumeAnyToken();
2354       }
2355       OpenMPClauseKind CKind = Tok.isAnnotation()
2356                                    ? OMPC_unknown
2357                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
2358       if (HasImplicitClause) {
2359         assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2360         if (DKind == OMPD_flush) {
2361           CKind = OMPC_flush;
2362         } else {
2363           assert(DKind == OMPD_depobj &&
2364                  "Expected flush or depobj directives.");
2365           CKind = OMPC_depobj;
2366         }
2367       }
2368       // No more implicit clauses allowed.
2369       ImplicitClauseAllowed = false;
2370       Actions.StartOpenMPClause(CKind);
2371       HasImplicitClause = false;
2372       OMPClause *Clause = ParseOpenMPClause(
2373           DKind, CKind, !FirstClauses[unsigned(CKind)].getInt());
2374       FirstClauses[unsigned(CKind)].setInt(true);
2375       if (Clause) {
2376         FirstClauses[unsigned(CKind)].setPointer(Clause);
2377         Clauses.push_back(Clause);
2378       }
2379 
2380       // Skip ',' if any.
2381       if (Tok.is(tok::comma))
2382         ConsumeToken();
2383       Actions.EndOpenMPClause();
2384     }
2385     // End location of the directive.
2386     EndLoc = Tok.getLocation();
2387     // Consume final annot_pragma_openmp_end.
2388     ConsumeAnnotationToken();
2389 
2390     // OpenMP [2.13.8, ordered Construct, Syntax]
2391     // If the depend clause is specified, the ordered construct is a stand-alone
2392     // directive.
2393     if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) {
2394       if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2395           ParsedStmtContext()) {
2396         Diag(Loc, diag::err_omp_immediate_directive)
2397             << getOpenMPDirectiveName(DKind) << 1
2398             << getOpenMPClauseName(OMPC_depend);
2399       }
2400       HasAssociatedStatement = false;
2401     }
2402 
2403     StmtResult AssociatedStmt;
2404     if (HasAssociatedStatement) {
2405       // The body is a block scope like in Lambdas and Blocks.
2406       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
2407       // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2408       // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2409       // should have at least one compound statement scope within it.
2410       ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2411       AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
2412       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2413     } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2414                DKind == OMPD_target_exit_data) {
2415       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
2416       AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2417                         Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
2418                                                   /*isStmtExpr=*/false));
2419       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2420     }
2421     Directive = Actions.ActOnOpenMPExecutableDirective(
2422         DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
2423         EndLoc);
2424 
2425     // Exit scope.
2426     Actions.EndOpenMPDSABlock(Directive.get());
2427     OMPDirectiveScope.Exit();
2428     break;
2429   }
2430   case OMPD_declare_simd:
2431   case OMPD_declare_target:
2432   case OMPD_end_declare_target:
2433   case OMPD_requires:
2434   case OMPD_begin_declare_variant:
2435   case OMPD_end_declare_variant:
2436   case OMPD_declare_variant:
2437     Diag(Tok, diag::err_omp_unexpected_directive)
2438         << 1 << getOpenMPDirectiveName(DKind);
2439     SkipUntil(tok::annot_pragma_openmp_end);
2440     break;
2441   case OMPD_unknown:
2442   default:
2443     Diag(Tok, diag::err_omp_unknown_directive);
2444     SkipUntil(tok::annot_pragma_openmp_end);
2445     break;
2446   }
2447   return Directive;
2448 }
2449 
2450 // Parses simple list:
2451 //   simple-variable-list:
2452 //         '(' id-expression {, id-expression} ')'
2453 //
ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,const llvm::function_ref<void (CXXScopeSpec &,DeclarationNameInfo)> & Callback,bool AllowScopeSpecifier)2454 bool Parser::ParseOpenMPSimpleVarList(
2455     OpenMPDirectiveKind Kind,
2456     const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
2457         &Callback,
2458     bool AllowScopeSpecifier) {
2459   // Parse '('.
2460   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2461   if (T.expectAndConsume(diag::err_expected_lparen_after,
2462                          getOpenMPDirectiveName(Kind).data()))
2463     return true;
2464   bool IsCorrect = true;
2465   bool NoIdentIsFound = true;
2466 
2467   // Read tokens while ')' or annot_pragma_openmp_end is not found.
2468   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
2469     CXXScopeSpec SS;
2470     UnqualifiedId Name;
2471     // Read var name.
2472     Token PrevTok = Tok;
2473     NoIdentIsFound = false;
2474 
2475     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2476         ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2477                                        /*ObjectHadErrors=*/false, false)) {
2478       IsCorrect = false;
2479       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2480                 StopBeforeMatch);
2481     } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2482                                   /*ObjectHadErrors=*/false, false, false,
2483                                   false, false, nullptr, Name)) {
2484       IsCorrect = false;
2485       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2486                 StopBeforeMatch);
2487     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
2488                Tok.isNot(tok::annot_pragma_openmp_end)) {
2489       IsCorrect = false;
2490       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2491                 StopBeforeMatch);
2492       Diag(PrevTok.getLocation(), diag::err_expected)
2493           << tok::identifier
2494           << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2495     } else {
2496       Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2497     }
2498     // Consume ','.
2499     if (Tok.is(tok::comma)) {
2500       ConsumeToken();
2501     }
2502   }
2503 
2504   if (NoIdentIsFound) {
2505     Diag(Tok, diag::err_expected) << tok::identifier;
2506     IsCorrect = false;
2507   }
2508 
2509   // Parse ')'.
2510   IsCorrect = !T.consumeClose() && IsCorrect;
2511 
2512   return !IsCorrect;
2513 }
2514 
ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind)2515 OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
2516   SourceLocation Loc = Tok.getLocation();
2517   ConsumeAnyToken();
2518 
2519   // Parse '('.
2520   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2521   if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
2522     return nullptr;
2523   SmallVector<Sema::UsesAllocatorsData, 4> Data;
2524   do {
2525     ExprResult Allocator = ParseCXXIdExpression();
2526     if (Allocator.isInvalid()) {
2527       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2528                 StopBeforeMatch);
2529       break;
2530     }
2531     Sema::UsesAllocatorsData &D = Data.emplace_back();
2532     D.Allocator = Allocator.get();
2533     if (Tok.is(tok::l_paren)) {
2534       BalancedDelimiterTracker T(*this, tok::l_paren,
2535                                  tok::annot_pragma_openmp_end);
2536       T.consumeOpen();
2537       ExprResult AllocatorTraits = ParseCXXIdExpression();
2538       T.consumeClose();
2539       if (AllocatorTraits.isInvalid()) {
2540         SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2541                   StopBeforeMatch);
2542         break;
2543       }
2544       D.AllocatorTraits = AllocatorTraits.get();
2545       D.LParenLoc = T.getOpenLocation();
2546       D.RParenLoc = T.getCloseLocation();
2547     }
2548     if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
2549       Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
2550     // Parse ','
2551     if (Tok.is(tok::comma))
2552       ConsumeAnyToken();
2553   } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
2554   T.consumeClose();
2555   return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(),
2556                                                 T.getCloseLocation(), Data);
2557 }
2558 
2559 /// Parsing of OpenMP clauses.
2560 ///
2561 ///    clause:
2562 ///       if-clause | final-clause | num_threads-clause | safelen-clause |
2563 ///       default-clause | private-clause | firstprivate-clause | shared-clause
2564 ///       | linear-clause | aligned-clause | collapse-clause |
2565 ///       lastprivate-clause | reduction-clause | proc_bind-clause |
2566 ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
2567 ///       mergeable-clause | flush-clause | read-clause | write-clause |
2568 ///       update-clause | capture-clause | seq_cst-clause | device-clause |
2569 ///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
2570 ///       thread_limit-clause | priority-clause | grainsize-clause |
2571 ///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
2572 ///       from-clause | is_device_ptr-clause | task_reduction-clause |
2573 ///       in_reduction-clause | allocator-clause | allocate-clause |
2574 ///       acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
2575 ///       depobj-clause | destroy-clause | detach-clause | inclusive-clause |
2576 ///       exclusive-clause | uses_allocators-clause | use_device_addr-clause
2577 ///
ParseOpenMPClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,bool FirstClause)2578 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
2579                                      OpenMPClauseKind CKind, bool FirstClause) {
2580   OMPClauseKind = CKind;
2581   OMPClause *Clause = nullptr;
2582   bool ErrorFound = false;
2583   bool WrongDirective = false;
2584   // Check if clause is allowed for the given directive.
2585   if (CKind != OMPC_unknown &&
2586       !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
2587     Diag(Tok, diag::err_omp_unexpected_clause)
2588         << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
2589     ErrorFound = true;
2590     WrongDirective = true;
2591   }
2592 
2593   switch (CKind) {
2594   case OMPC_final:
2595   case OMPC_num_threads:
2596   case OMPC_safelen:
2597   case OMPC_simdlen:
2598   case OMPC_collapse:
2599   case OMPC_ordered:
2600   case OMPC_num_teams:
2601   case OMPC_thread_limit:
2602   case OMPC_priority:
2603   case OMPC_grainsize:
2604   case OMPC_num_tasks:
2605   case OMPC_hint:
2606   case OMPC_allocator:
2607   case OMPC_depobj:
2608   case OMPC_detach:
2609     // OpenMP [2.5, Restrictions]
2610     //  At most one num_threads clause can appear on the directive.
2611     // OpenMP [2.8.1, simd construct, Restrictions]
2612     //  Only one safelen  clause can appear on a simd directive.
2613     //  Only one simdlen  clause can appear on a simd directive.
2614     //  Only one collapse clause can appear on a simd directive.
2615     // OpenMP [2.11.1, task Construct, Restrictions]
2616     //  At most one if clause can appear on the directive.
2617     //  At most one final clause can appear on the directive.
2618     // OpenMP [teams Construct, Restrictions]
2619     //  At most one num_teams clause can appear on the directive.
2620     //  At most one thread_limit clause can appear on the directive.
2621     // OpenMP [2.9.1, task Construct, Restrictions]
2622     // At most one priority clause can appear on the directive.
2623     // OpenMP [2.9.2, taskloop Construct, Restrictions]
2624     // At most one grainsize clause can appear on the directive.
2625     // OpenMP [2.9.2, taskloop Construct, Restrictions]
2626     // At most one num_tasks clause can appear on the directive.
2627     // OpenMP [2.11.3, allocate Directive, Restrictions]
2628     // At most one allocator clause can appear on the directive.
2629     // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
2630     // At most one detach clause can appear on the directive.
2631     if (!FirstClause) {
2632       Diag(Tok, diag::err_omp_more_one_clause)
2633           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2634       ErrorFound = true;
2635     }
2636 
2637     if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
2638       Clause = ParseOpenMPClause(CKind, WrongDirective);
2639     else
2640       Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
2641     break;
2642   case OMPC_default:
2643   case OMPC_proc_bind:
2644   case OMPC_atomic_default_mem_order:
2645   case OMPC_order:
2646     // OpenMP [2.14.3.1, Restrictions]
2647     //  Only a single default clause may be specified on a parallel, task or
2648     //  teams directive.
2649     // OpenMP [2.5, parallel Construct, Restrictions]
2650     //  At most one proc_bind clause can appear on the directive.
2651     // OpenMP [5.0, Requires directive, Restrictions]
2652     //  At most one atomic_default_mem_order clause can appear
2653     //  on the directive
2654     if (!FirstClause && CKind != OMPC_order) {
2655       Diag(Tok, diag::err_omp_more_one_clause)
2656           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2657       ErrorFound = true;
2658     }
2659 
2660     Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
2661     break;
2662   case OMPC_device:
2663   case OMPC_schedule:
2664   case OMPC_dist_schedule:
2665   case OMPC_defaultmap:
2666     // OpenMP [2.7.1, Restrictions, p. 3]
2667     //  Only one schedule clause can appear on a loop directive.
2668     // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
2669     //  At most one defaultmap clause can appear on the directive.
2670     // OpenMP 5.0 [2.12.5, target construct, Restrictions]
2671     //  At most one device clause can appear on the directive.
2672     if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
2673         !FirstClause) {
2674       Diag(Tok, diag::err_omp_more_one_clause)
2675           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2676       ErrorFound = true;
2677     }
2678     LLVM_FALLTHROUGH;
2679   case OMPC_if:
2680     Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
2681     break;
2682   case OMPC_nowait:
2683   case OMPC_untied:
2684   case OMPC_mergeable:
2685   case OMPC_read:
2686   case OMPC_write:
2687   case OMPC_capture:
2688   case OMPC_seq_cst:
2689   case OMPC_acq_rel:
2690   case OMPC_acquire:
2691   case OMPC_release:
2692   case OMPC_relaxed:
2693   case OMPC_threads:
2694   case OMPC_simd:
2695   case OMPC_nogroup:
2696   case OMPC_unified_address:
2697   case OMPC_unified_shared_memory:
2698   case OMPC_reverse_offload:
2699   case OMPC_dynamic_allocators:
2700   case OMPC_destroy:
2701     // OpenMP [2.7.1, Restrictions, p. 9]
2702     //  Only one ordered clause can appear on a loop directive.
2703     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
2704     //  Only one nowait clause can appear on a for directive.
2705     // OpenMP [5.0, Requires directive, Restrictions]
2706     //   Each of the requires clauses can appear at most once on the directive.
2707     if (!FirstClause) {
2708       Diag(Tok, diag::err_omp_more_one_clause)
2709           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2710       ErrorFound = true;
2711     }
2712 
2713     Clause = ParseOpenMPClause(CKind, WrongDirective);
2714     break;
2715   case OMPC_update:
2716     if (!FirstClause) {
2717       Diag(Tok, diag::err_omp_more_one_clause)
2718           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
2719       ErrorFound = true;
2720     }
2721 
2722     Clause = (DKind == OMPD_depobj)
2723                  ? ParseOpenMPSimpleClause(CKind, WrongDirective)
2724                  : ParseOpenMPClause(CKind, WrongDirective);
2725     break;
2726   case OMPC_private:
2727   case OMPC_firstprivate:
2728   case OMPC_lastprivate:
2729   case OMPC_shared:
2730   case OMPC_reduction:
2731   case OMPC_task_reduction:
2732   case OMPC_in_reduction:
2733   case OMPC_linear:
2734   case OMPC_aligned:
2735   case OMPC_copyin:
2736   case OMPC_copyprivate:
2737   case OMPC_flush:
2738   case OMPC_depend:
2739   case OMPC_map:
2740   case OMPC_to:
2741   case OMPC_from:
2742   case OMPC_use_device_ptr:
2743   case OMPC_use_device_addr:
2744   case OMPC_is_device_ptr:
2745   case OMPC_allocate:
2746   case OMPC_nontemporal:
2747   case OMPC_inclusive:
2748   case OMPC_exclusive:
2749   case OMPC_affinity:
2750     Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
2751     break;
2752   case OMPC_uses_allocators:
2753     Clause = ParseOpenMPUsesAllocatorClause(DKind);
2754     break;
2755   case OMPC_device_type:
2756   case OMPC_unknown:
2757     skipUntilPragmaOpenMPEnd(DKind);
2758     break;
2759   case OMPC_threadprivate:
2760   case OMPC_uniform:
2761   case OMPC_match:
2762     if (!WrongDirective)
2763       Diag(Tok, diag::err_omp_unexpected_clause)
2764           << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
2765     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
2766     break;
2767   default:
2768     break;
2769   }
2770   return ErrorFound ? nullptr : Clause;
2771 }
2772 
2773 /// Parses simple expression in parens for single-expression clauses of OpenMP
2774 /// constructs.
2775 /// \param RLoc Returned location of right paren.
ParseOpenMPParensExpr(StringRef ClauseName,SourceLocation & RLoc,bool IsAddressOfOperand)2776 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
2777                                          SourceLocation &RLoc,
2778                                          bool IsAddressOfOperand) {
2779   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2780   if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
2781     return ExprError();
2782 
2783   SourceLocation ELoc = Tok.getLocation();
2784   ExprResult LHS(
2785       ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast));
2786   ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
2787   Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2788 
2789   // Parse ')'.
2790   RLoc = Tok.getLocation();
2791   if (!T.consumeClose())
2792     RLoc = T.getCloseLocation();
2793 
2794   return Val;
2795 }
2796 
2797 /// Parsing of OpenMP clauses with single expressions like 'final',
2798 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
2799 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
2800 /// 'detach'.
2801 ///
2802 ///    final-clause:
2803 ///      'final' '(' expression ')'
2804 ///
2805 ///    num_threads-clause:
2806 ///      'num_threads' '(' expression ')'
2807 ///
2808 ///    safelen-clause:
2809 ///      'safelen' '(' expression ')'
2810 ///
2811 ///    simdlen-clause:
2812 ///      'simdlen' '(' expression ')'
2813 ///
2814 ///    collapse-clause:
2815 ///      'collapse' '(' expression ')'
2816 ///
2817 ///    priority-clause:
2818 ///      'priority' '(' expression ')'
2819 ///
2820 ///    grainsize-clause:
2821 ///      'grainsize' '(' expression ')'
2822 ///
2823 ///    num_tasks-clause:
2824 ///      'num_tasks' '(' expression ')'
2825 ///
2826 ///    hint-clause:
2827 ///      'hint' '(' expression ')'
2828 ///
2829 ///    allocator-clause:
2830 ///      'allocator' '(' expression ')'
2831 ///
2832 ///    detach-clause:
2833 ///      'detach' '(' event-handler-expression ')'
2834 ///
ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,bool ParseOnly)2835 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
2836                                                bool ParseOnly) {
2837   SourceLocation Loc = ConsumeToken();
2838   SourceLocation LLoc = Tok.getLocation();
2839   SourceLocation RLoc;
2840 
2841   ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
2842 
2843   if (Val.isInvalid())
2844     return nullptr;
2845 
2846   if (ParseOnly)
2847     return nullptr;
2848   return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
2849 }
2850 
2851 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
2852 ///
2853 ///    default-clause:
2854 ///         'default' '(' 'none' | 'shared' | 'firstprivate' ')'
2855 ///
2856 ///    proc_bind-clause:
2857 ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')'
2858 ///
2859 ///    update-clause:
2860 ///         'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')'
2861 ///
ParseOpenMPSimpleClause(OpenMPClauseKind Kind,bool ParseOnly)2862 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
2863                                            bool ParseOnly) {
2864   llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
2865   if (!Val || ParseOnly)
2866     return nullptr;
2867   if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
2868       static_cast<DefaultKind>(Val.getValue().Type) ==
2869           OMP_DEFAULT_firstprivate) {
2870     Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa)
2871         << getOpenMPClauseName(OMPC_firstprivate)
2872         << getOpenMPClauseName(OMPC_default) << "5.1";
2873     return nullptr;
2874   }
2875   return Actions.ActOnOpenMPSimpleClause(
2876       Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
2877       Val.getValue().Loc, Val.getValue().RLoc);
2878 }
2879 
2880 /// Parsing of OpenMP clauses like 'ordered'.
2881 ///
2882 ///    ordered-clause:
2883 ///         'ordered'
2884 ///
2885 ///    nowait-clause:
2886 ///         'nowait'
2887 ///
2888 ///    untied-clause:
2889 ///         'untied'
2890 ///
2891 ///    mergeable-clause:
2892 ///         'mergeable'
2893 ///
2894 ///    read-clause:
2895 ///         'read'
2896 ///
2897 ///    threads-clause:
2898 ///         'threads'
2899 ///
2900 ///    simd-clause:
2901 ///         'simd'
2902 ///
2903 ///    nogroup-clause:
2904 ///         'nogroup'
2905 ///
ParseOpenMPClause(OpenMPClauseKind Kind,bool ParseOnly)2906 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
2907   SourceLocation Loc = Tok.getLocation();
2908   ConsumeAnyToken();
2909 
2910   if (ParseOnly)
2911     return nullptr;
2912   return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
2913 }
2914 
2915 /// Parsing of OpenMP clauses with single expressions and some additional
2916 /// argument like 'schedule' or 'dist_schedule'.
2917 ///
2918 ///    schedule-clause:
2919 ///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
2920 ///      ')'
2921 ///
2922 ///    if-clause:
2923 ///      'if' '(' [ directive-name-modifier ':' ] expression ')'
2924 ///
2925 ///    defaultmap:
2926 ///      'defaultmap' '(' modifier [ ':' kind ] ')'
2927 ///
2928 ///    device-clause:
2929 ///      'device' '(' [ device-modifier ':' ] expression ')'
2930 ///
ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,bool ParseOnly)2931 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
2932                                                       OpenMPClauseKind Kind,
2933                                                       bool ParseOnly) {
2934   SourceLocation Loc = ConsumeToken();
2935   SourceLocation DelimLoc;
2936   // Parse '('.
2937   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2938   if (T.expectAndConsume(diag::err_expected_lparen_after,
2939                          getOpenMPClauseName(Kind).data()))
2940     return nullptr;
2941 
2942   ExprResult Val;
2943   SmallVector<unsigned, 4> Arg;
2944   SmallVector<SourceLocation, 4> KLoc;
2945   if (Kind == OMPC_schedule) {
2946     enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
2947     Arg.resize(NumberOfElements);
2948     KLoc.resize(NumberOfElements);
2949     Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
2950     Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
2951     Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
2952     unsigned KindModifier = getOpenMPSimpleClauseType(
2953         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
2954         getLangOpts().OpenMP);
2955     if (KindModifier > OMPC_SCHEDULE_unknown) {
2956       // Parse 'modifier'
2957       Arg[Modifier1] = KindModifier;
2958       KLoc[Modifier1] = Tok.getLocation();
2959       if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2960           Tok.isNot(tok::annot_pragma_openmp_end))
2961         ConsumeAnyToken();
2962       if (Tok.is(tok::comma)) {
2963         // Parse ',' 'modifier'
2964         ConsumeAnyToken();
2965         KindModifier = getOpenMPSimpleClauseType(
2966             Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
2967             getLangOpts().OpenMP);
2968         Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
2969                              ? KindModifier
2970                              : (unsigned)OMPC_SCHEDULE_unknown;
2971         KLoc[Modifier2] = Tok.getLocation();
2972         if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2973             Tok.isNot(tok::annot_pragma_openmp_end))
2974           ConsumeAnyToken();
2975       }
2976       // Parse ':'
2977       if (Tok.is(tok::colon))
2978         ConsumeAnyToken();
2979       else
2980         Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
2981       KindModifier = getOpenMPSimpleClauseType(
2982           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
2983           getLangOpts().OpenMP);
2984     }
2985     Arg[ScheduleKind] = KindModifier;
2986     KLoc[ScheduleKind] = Tok.getLocation();
2987     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
2988         Tok.isNot(tok::annot_pragma_openmp_end))
2989       ConsumeAnyToken();
2990     if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
2991          Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
2992          Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
2993         Tok.is(tok::comma))
2994       DelimLoc = ConsumeAnyToken();
2995   } else if (Kind == OMPC_dist_schedule) {
2996     Arg.push_back(getOpenMPSimpleClauseType(
2997         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
2998         getLangOpts().OpenMP));
2999     KLoc.push_back(Tok.getLocation());
3000     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3001         Tok.isNot(tok::annot_pragma_openmp_end))
3002       ConsumeAnyToken();
3003     if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
3004       DelimLoc = ConsumeAnyToken();
3005   } else if (Kind == OMPC_defaultmap) {
3006     // Get a defaultmap modifier
3007     unsigned Modifier = getOpenMPSimpleClauseType(
3008         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3009         getLangOpts().OpenMP);
3010     // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
3011     // pointer
3012     if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
3013       Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
3014     Arg.push_back(Modifier);
3015     KLoc.push_back(Tok.getLocation());
3016     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3017         Tok.isNot(tok::annot_pragma_openmp_end))
3018       ConsumeAnyToken();
3019     // Parse ':'
3020     if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
3021       if (Tok.is(tok::colon))
3022         ConsumeAnyToken();
3023       else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
3024         Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
3025       // Get a defaultmap kind
3026       Arg.push_back(getOpenMPSimpleClauseType(
3027           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3028           getLangOpts().OpenMP));
3029       KLoc.push_back(Tok.getLocation());
3030       if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3031           Tok.isNot(tok::annot_pragma_openmp_end))
3032         ConsumeAnyToken();
3033     } else {
3034       Arg.push_back(OMPC_DEFAULTMAP_unknown);
3035       KLoc.push_back(SourceLocation());
3036     }
3037   } else if (Kind == OMPC_device) {
3038     // Only target executable directives support extended device construct.
3039     if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
3040         NextToken().is(tok::colon)) {
3041       // Parse optional <device modifier> ':'
3042       Arg.push_back(getOpenMPSimpleClauseType(
3043           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3044           getLangOpts().OpenMP));
3045       KLoc.push_back(Tok.getLocation());
3046       ConsumeAnyToken();
3047       // Parse ':'
3048       ConsumeAnyToken();
3049     } else {
3050       Arg.push_back(OMPC_DEVICE_unknown);
3051       KLoc.emplace_back();
3052     }
3053   } else {
3054     assert(Kind == OMPC_if);
3055     KLoc.push_back(Tok.getLocation());
3056     TentativeParsingAction TPA(*this);
3057     auto DK = parseOpenMPDirectiveKind(*this);
3058     Arg.push_back(DK);
3059     if (DK != OMPD_unknown) {
3060       ConsumeToken();
3061       if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
3062         TPA.Commit();
3063         DelimLoc = ConsumeToken();
3064       } else {
3065         TPA.Revert();
3066         Arg.back() = unsigned(OMPD_unknown);
3067       }
3068     } else {
3069       TPA.Revert();
3070     }
3071   }
3072 
3073   bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
3074                           (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
3075                           Kind == OMPC_if || Kind == OMPC_device;
3076   if (NeedAnExpression) {
3077     SourceLocation ELoc = Tok.getLocation();
3078     ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
3079     Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3080     Val =
3081         Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3082   }
3083 
3084   // Parse ')'.
3085   SourceLocation RLoc = Tok.getLocation();
3086   if (!T.consumeClose())
3087     RLoc = T.getCloseLocation();
3088 
3089   if (NeedAnExpression && Val.isInvalid())
3090     return nullptr;
3091 
3092   if (ParseOnly)
3093     return nullptr;
3094   return Actions.ActOnOpenMPSingleExprWithArgClause(
3095       Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
3096 }
3097 
ParseReductionId(Parser & P,CXXScopeSpec & ReductionIdScopeSpec,UnqualifiedId & ReductionId)3098 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
3099                              UnqualifiedId &ReductionId) {
3100   if (ReductionIdScopeSpec.isEmpty()) {
3101     auto OOK = OO_None;
3102     switch (P.getCurToken().getKind()) {
3103     case tok::plus:
3104       OOK = OO_Plus;
3105       break;
3106     case tok::minus:
3107       OOK = OO_Minus;
3108       break;
3109     case tok::star:
3110       OOK = OO_Star;
3111       break;
3112     case tok::amp:
3113       OOK = OO_Amp;
3114       break;
3115     case tok::pipe:
3116       OOK = OO_Pipe;
3117       break;
3118     case tok::caret:
3119       OOK = OO_Caret;
3120       break;
3121     case tok::ampamp:
3122       OOK = OO_AmpAmp;
3123       break;
3124     case tok::pipepipe:
3125       OOK = OO_PipePipe;
3126       break;
3127     default:
3128       break;
3129     }
3130     if (OOK != OO_None) {
3131       SourceLocation OpLoc = P.ConsumeToken();
3132       SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
3133       ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
3134       return false;
3135     }
3136   }
3137   return P.ParseUnqualifiedId(
3138       ReductionIdScopeSpec, /*ObjectType=*/nullptr,
3139       /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
3140       /*AllowDestructorName*/ false,
3141       /*AllowConstructorName*/ false,
3142       /*AllowDeductionGuide*/ false, nullptr, ReductionId);
3143 }
3144 
3145 /// Checks if the token is a valid map-type-modifier.
3146 /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
isMapModifier(Parser & P)3147 static OpenMPMapModifierKind isMapModifier(Parser &P) {
3148   Token Tok = P.getCurToken();
3149   if (!Tok.is(tok::identifier))
3150     return OMPC_MAP_MODIFIER_unknown;
3151 
3152   Preprocessor &PP = P.getPreprocessor();
3153   OpenMPMapModifierKind TypeModifier =
3154       static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(
3155           OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP));
3156   return TypeModifier;
3157 }
3158 
3159 /// Parse the mapper modifier in map, to, and from clauses.
parseMapperModifier(OpenMPVarListDataTy & Data)3160 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
3161   // Parse '('.
3162   BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
3163   if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
3164     SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3165               StopBeforeMatch);
3166     return true;
3167   }
3168   // Parse mapper-identifier
3169   if (getLangOpts().CPlusPlus)
3170     ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
3171                                    /*ObjectType=*/nullptr,
3172                                    /*ObjectHadErrors=*/false,
3173                                    /*EnteringContext=*/false);
3174   if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
3175     Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
3176     SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3177               StopBeforeMatch);
3178     return true;
3179   }
3180   auto &DeclNames = Actions.getASTContext().DeclarationNames;
3181   Data.ReductionOrMapperId = DeclarationNameInfo(
3182       DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
3183   ConsumeToken();
3184   // Parse ')'.
3185   return T.consumeClose();
3186 }
3187 
3188 /// Parse map-type-modifiers in map clause.
3189 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
3190 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
3191 /// present
parseMapTypeModifiers(OpenMPVarListDataTy & Data)3192 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
3193   while (getCurToken().isNot(tok::colon)) {
3194     OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
3195     if (TypeModifier == OMPC_MAP_MODIFIER_always ||
3196         TypeModifier == OMPC_MAP_MODIFIER_close ||
3197         TypeModifier == OMPC_MAP_MODIFIER_present) {
3198       Data.MapTypeModifiers.push_back(TypeModifier);
3199       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
3200       ConsumeToken();
3201     } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
3202       Data.MapTypeModifiers.push_back(TypeModifier);
3203       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
3204       ConsumeToken();
3205       if (parseMapperModifier(Data))
3206         return true;
3207     } else {
3208       // For the case of unknown map-type-modifier or a map-type.
3209       // Map-type is followed by a colon; the function returns when it
3210       // encounters a token followed by a colon.
3211       if (Tok.is(tok::comma)) {
3212         Diag(Tok, diag::err_omp_map_type_modifier_missing);
3213         ConsumeToken();
3214         continue;
3215       }
3216       // Potential map-type token as it is followed by a colon.
3217       if (PP.LookAhead(0).is(tok::colon))
3218         return false;
3219       Diag(Tok, diag::err_omp_unknown_map_type_modifier)
3220           << (getLangOpts().OpenMP >= 51 ? 1 : 0);
3221       ConsumeToken();
3222     }
3223     if (getCurToken().is(tok::comma))
3224       ConsumeToken();
3225   }
3226   return false;
3227 }
3228 
3229 /// Checks if the token is a valid map-type.
3230 /// FIXME: It will return an OpenMPMapModifierKind if that's what it parses.
isMapType(Parser & P)3231 static OpenMPMapClauseKind isMapType(Parser &P) {
3232   Token Tok = P.getCurToken();
3233   // The map-type token can be either an identifier or the C++ delete keyword.
3234   if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
3235     return OMPC_MAP_unknown;
3236   Preprocessor &PP = P.getPreprocessor();
3237   OpenMPMapClauseKind MapType =
3238       static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
3239           OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP));
3240   return MapType;
3241 }
3242 
3243 /// Parse map-type in map clause.
3244 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
3245 /// where, map-type ::= to | from | tofrom | alloc | release | delete
parseMapType(Parser & P,Parser::OpenMPVarListDataTy & Data)3246 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
3247   Token Tok = P.getCurToken();
3248   if (Tok.is(tok::colon)) {
3249     P.Diag(Tok, diag::err_omp_map_type_missing);
3250     return;
3251   }
3252   Data.ExtraModifier = isMapType(P);
3253   if (Data.ExtraModifier == OMPC_MAP_unknown)
3254     P.Diag(Tok, diag::err_omp_unknown_map_type);
3255   P.ConsumeToken();
3256 }
3257 
3258 /// Parses simple expression in parens for single-expression clauses of OpenMP
3259 /// constructs.
ParseOpenMPIteratorsExpr()3260 ExprResult Parser::ParseOpenMPIteratorsExpr() {
3261   assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
3262          "Expected 'iterator' token.");
3263   SourceLocation IteratorKwLoc = ConsumeToken();
3264 
3265   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3266   if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
3267     return ExprError();
3268 
3269   SourceLocation LLoc = T.getOpenLocation();
3270   SmallVector<Sema::OMPIteratorData, 4> Data;
3271   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
3272     // Check if the type parsing is required.
3273     ParsedType IteratorType;
3274     if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
3275       // identifier '=' is not found - parse type.
3276       TypeResult TR = ParseTypeName();
3277       if (TR.isInvalid()) {
3278         T.skipToEnd();
3279         return ExprError();
3280       }
3281       IteratorType = TR.get();
3282     }
3283 
3284     // Parse identifier.
3285     IdentifierInfo *II = nullptr;
3286     SourceLocation IdLoc;
3287     if (Tok.is(tok::identifier)) {
3288       II = Tok.getIdentifierInfo();
3289       IdLoc = ConsumeToken();
3290     } else {
3291       Diag(Tok, diag::err_expected_unqualified_id) << 0;
3292     }
3293 
3294     // Parse '='.
3295     SourceLocation AssignLoc;
3296     if (Tok.is(tok::equal))
3297       AssignLoc = ConsumeToken();
3298     else
3299       Diag(Tok, diag::err_omp_expected_equal_in_iterator);
3300 
3301     // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
3302     ColonProtectionRAIIObject ColonRAII(*this);
3303     // Parse <begin>
3304     SourceLocation Loc = Tok.getLocation();
3305     ExprResult LHS = ParseCastExpression(AnyCastExpr);
3306     ExprResult Begin = Actions.CorrectDelayedTyposInExpr(
3307         ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3308     Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
3309                                         /*DiscardedValue=*/false);
3310     // Parse ':'.
3311     SourceLocation ColonLoc;
3312     if (Tok.is(tok::colon))
3313       ColonLoc = ConsumeToken();
3314 
3315     // Parse <end>
3316     Loc = Tok.getLocation();
3317     LHS = ParseCastExpression(AnyCastExpr);
3318     ExprResult End = Actions.CorrectDelayedTyposInExpr(
3319         ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3320     End = Actions.ActOnFinishFullExpr(End.get(), Loc,
3321                                       /*DiscardedValue=*/false);
3322 
3323     SourceLocation SecColonLoc;
3324     ExprResult Step;
3325     // Parse optional step.
3326     if (Tok.is(tok::colon)) {
3327       // Parse ':'
3328       SecColonLoc = ConsumeToken();
3329       // Parse <step>
3330       Loc = Tok.getLocation();
3331       LHS = ParseCastExpression(AnyCastExpr);
3332       Step = Actions.CorrectDelayedTyposInExpr(
3333           ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3334       Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
3335                                          /*DiscardedValue=*/false);
3336     }
3337 
3338     // Parse ',' or ')'
3339     if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3340       Diag(Tok, diag::err_omp_expected_punc_after_iterator);
3341     if (Tok.is(tok::comma))
3342       ConsumeToken();
3343 
3344     Sema::OMPIteratorData &D = Data.emplace_back();
3345     D.DeclIdent = II;
3346     D.DeclIdentLoc = IdLoc;
3347     D.Type = IteratorType;
3348     D.AssignLoc = AssignLoc;
3349     D.ColonLoc = ColonLoc;
3350     D.SecColonLoc = SecColonLoc;
3351     D.Range.Begin = Begin.get();
3352     D.Range.End = End.get();
3353     D.Range.Step = Step.get();
3354   }
3355 
3356   // Parse ')'.
3357   SourceLocation RLoc = Tok.getLocation();
3358   if (!T.consumeClose())
3359     RLoc = T.getCloseLocation();
3360 
3361   return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc,
3362                                       Data);
3363 }
3364 
3365 /// Parses clauses with list.
ParseOpenMPVarList(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,SmallVectorImpl<Expr * > & Vars,OpenMPVarListDataTy & Data)3366 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
3367                                 OpenMPClauseKind Kind,
3368                                 SmallVectorImpl<Expr *> &Vars,
3369                                 OpenMPVarListDataTy &Data) {
3370   UnqualifiedId UnqualifiedReductionId;
3371   bool InvalidReductionId = false;
3372   bool IsInvalidMapperModifier = false;
3373 
3374   // Parse '('.
3375   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3376   if (T.expectAndConsume(diag::err_expected_lparen_after,
3377                          getOpenMPClauseName(Kind).data()))
3378     return true;
3379 
3380   bool HasIterator = false;
3381   bool NeedRParenForLinear = false;
3382   BalancedDelimiterTracker LinearT(*this, tok::l_paren,
3383                                    tok::annot_pragma_openmp_end);
3384   // Handle reduction-identifier for reduction clause.
3385   if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
3386       Kind == OMPC_in_reduction) {
3387     Data.ExtraModifier = OMPC_REDUCTION_unknown;
3388     if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
3389         (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
3390         NextToken().is(tok::comma)) {
3391       // Parse optional reduction modifier.
3392       Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
3393                                                      getLangOpts().OpenMP);
3394       Data.ExtraModifierLoc = Tok.getLocation();
3395       ConsumeToken();
3396       assert(Tok.is(tok::comma) && "Expected comma.");
3397       (void)ConsumeToken();
3398     }
3399     ColonProtectionRAIIObject ColonRAII(*this);
3400     if (getLangOpts().CPlusPlus)
3401       ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
3402                                      /*ObjectType=*/nullptr,
3403                                      /*ObjectHadErrors=*/false,
3404                                      /*EnteringContext=*/false);
3405     InvalidReductionId = ParseReductionId(
3406         *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
3407     if (InvalidReductionId) {
3408       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3409                 StopBeforeMatch);
3410     }
3411     if (Tok.is(tok::colon))
3412       Data.ColonLoc = ConsumeToken();
3413     else
3414       Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
3415     if (!InvalidReductionId)
3416       Data.ReductionOrMapperId =
3417           Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
3418   } else if (Kind == OMPC_depend) {
3419     if (getLangOpts().OpenMP >= 50) {
3420       if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
3421         // Handle optional dependence modifier.
3422         // iterator(iterators-definition)
3423         // where iterators-definition is iterator-specifier [,
3424         // iterators-definition ]
3425         // where iterator-specifier is [ iterator-type ] identifier =
3426         // range-specification
3427         HasIterator = true;
3428         EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
3429         ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
3430         Data.DepModOrTailExpr = IteratorRes.get();
3431         // Parse ','
3432         ExpectAndConsume(tok::comma);
3433       }
3434     }
3435     // Handle dependency type for depend clause.
3436     ColonProtectionRAIIObject ColonRAII(*this);
3437     Data.ExtraModifier = getOpenMPSimpleClauseType(
3438         Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
3439         getLangOpts().OpenMP);
3440     Data.ExtraModifierLoc = Tok.getLocation();
3441     if (Data.ExtraModifier == OMPC_DEPEND_unknown) {
3442       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3443                 StopBeforeMatch);
3444     } else {
3445       ConsumeToken();
3446       // Special processing for depend(source) clause.
3447       if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) {
3448         // Parse ')'.
3449         T.consumeClose();
3450         return false;
3451       }
3452     }
3453     if (Tok.is(tok::colon)) {
3454       Data.ColonLoc = ConsumeToken();
3455     } else {
3456       Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
3457                                       : diag::warn_pragma_expected_colon)
3458           << "dependency type";
3459     }
3460   } else if (Kind == OMPC_linear) {
3461     // Try to parse modifier if any.
3462     Data.ExtraModifier = OMPC_LINEAR_val;
3463     if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
3464       Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
3465                                                      getLangOpts().OpenMP);
3466       Data.ExtraModifierLoc = ConsumeToken();
3467       LinearT.consumeOpen();
3468       NeedRParenForLinear = true;
3469     }
3470   } else if (Kind == OMPC_lastprivate) {
3471     // Try to parse modifier if any.
3472     Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
3473     // Conditional modifier allowed only in OpenMP 5.0 and not supported in
3474     // distribute and taskloop based directives.
3475     if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
3476          !isOpenMPTaskLoopDirective(DKind)) &&
3477         Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
3478       Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok),
3479                                                      getLangOpts().OpenMP);
3480       Data.ExtraModifierLoc = Tok.getLocation();
3481       ConsumeToken();
3482       assert(Tok.is(tok::colon) && "Expected colon.");
3483       Data.ColonLoc = ConsumeToken();
3484     }
3485   } else if (Kind == OMPC_map) {
3486     // Handle map type for map clause.
3487     ColonProtectionRAIIObject ColonRAII(*this);
3488 
3489     // The first identifier may be a list item, a map-type or a
3490     // map-type-modifier. The map-type can also be delete which has the same
3491     // spelling of the C++ delete keyword.
3492     Data.ExtraModifier = OMPC_MAP_unknown;
3493     Data.ExtraModifierLoc = Tok.getLocation();
3494 
3495     // Check for presence of a colon in the map clause.
3496     TentativeParsingAction TPA(*this);
3497     bool ColonPresent = false;
3498     if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3499                   StopBeforeMatch)) {
3500       if (Tok.is(tok::colon))
3501         ColonPresent = true;
3502     }
3503     TPA.Revert();
3504     // Only parse map-type-modifier[s] and map-type if a colon is present in
3505     // the map clause.
3506     if (ColonPresent) {
3507       IsInvalidMapperModifier = parseMapTypeModifiers(Data);
3508       if (!IsInvalidMapperModifier)
3509         parseMapType(*this, Data);
3510       else
3511         SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
3512     }
3513     if (Data.ExtraModifier == OMPC_MAP_unknown) {
3514       Data.ExtraModifier = OMPC_MAP_tofrom;
3515       Data.IsMapTypeImplicit = true;
3516     }
3517 
3518     if (Tok.is(tok::colon))
3519       Data.ColonLoc = ConsumeToken();
3520   } else if (Kind == OMPC_to || Kind == OMPC_from) {
3521     while (Tok.is(tok::identifier)) {
3522       auto Modifier =
3523           static_cast<OpenMPMotionModifierKind>(getOpenMPSimpleClauseType(
3524               Kind, PP.getSpelling(Tok), getLangOpts().OpenMP));
3525       if (Modifier == OMPC_MOTION_MODIFIER_unknown)
3526         break;
3527       Data.MotionModifiers.push_back(Modifier);
3528       Data.MotionModifiersLoc.push_back(Tok.getLocation());
3529       ConsumeToken();
3530       if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
3531         IsInvalidMapperModifier = parseMapperModifier(Data);
3532         if (IsInvalidMapperModifier)
3533           break;
3534       }
3535       // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
3536       if (getLangOpts().OpenMP < 51)
3537         break;
3538       // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
3539       // TODO: Is that intentional?
3540       if (Tok.is(tok::comma))
3541         ConsumeToken();
3542     }
3543     if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
3544       if (!IsInvalidMapperModifier) {
3545         if (getLangOpts().OpenMP < 51)
3546           Diag(Tok, diag::warn_pragma_expected_colon) << ")";
3547         else
3548           Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
3549       }
3550       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
3551                 StopBeforeMatch);
3552     }
3553     // OpenMP 5.1 permits a ':' even without a preceding modifier.  TODO: Is
3554     // that intentional?
3555     if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
3556         Tok.is(tok::colon))
3557       Data.ColonLoc = ConsumeToken();
3558   } else if (Kind == OMPC_allocate ||
3559              (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
3560               PP.getSpelling(Tok) == "iterator")) {
3561     // Handle optional allocator expression followed by colon delimiter.
3562     ColonProtectionRAIIObject ColonRAII(*this);
3563     TentativeParsingAction TPA(*this);
3564     // OpenMP 5.0, 2.10.1, task Construct.
3565     // where aff-modifier is one of the following:
3566     // iterator(iterators-definition)
3567     ExprResult Tail;
3568     if (Kind == OMPC_allocate) {
3569       Tail = ParseAssignmentExpression();
3570     } else {
3571       HasIterator = true;
3572       EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
3573       Tail = ParseOpenMPIteratorsExpr();
3574     }
3575     Tail = Actions.CorrectDelayedTyposInExpr(Tail);
3576     Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
3577                                        /*DiscardedValue=*/false);
3578     if (Tail.isUsable()) {
3579       if (Tok.is(tok::colon)) {
3580         Data.DepModOrTailExpr = Tail.get();
3581         Data.ColonLoc = ConsumeToken();
3582         TPA.Commit();
3583       } else {
3584         // Colon not found, parse only list of variables.
3585         TPA.Revert();
3586       }
3587     } else {
3588       // Parsing was unsuccessfull, revert and skip to the end of clause or
3589       // directive.
3590       TPA.Revert();
3591       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3592                 StopBeforeMatch);
3593     }
3594   }
3595 
3596   bool IsComma =
3597       (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
3598        Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
3599       (Kind == OMPC_reduction && !InvalidReductionId) ||
3600       (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
3601       (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
3602   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
3603   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
3604                      Tok.isNot(tok::annot_pragma_openmp_end))) {
3605     ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
3606     ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
3607     // Parse variable
3608     ExprResult VarExpr =
3609         Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
3610     if (VarExpr.isUsable()) {
3611       Vars.push_back(VarExpr.get());
3612     } else {
3613       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3614                 StopBeforeMatch);
3615     }
3616     // Skip ',' if any
3617     IsComma = Tok.is(tok::comma);
3618     if (IsComma)
3619       ConsumeToken();
3620     else if (Tok.isNot(tok::r_paren) &&
3621              Tok.isNot(tok::annot_pragma_openmp_end) &&
3622              (!MayHaveTail || Tok.isNot(tok::colon)))
3623       Diag(Tok, diag::err_omp_expected_punc)
3624           << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
3625                                    : getOpenMPClauseName(Kind))
3626           << (Kind == OMPC_flush);
3627   }
3628 
3629   // Parse ')' for linear clause with modifier.
3630   if (NeedRParenForLinear)
3631     LinearT.consumeClose();
3632 
3633   // Parse ':' linear-step (or ':' alignment).
3634   const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
3635   if (MustHaveTail) {
3636     Data.ColonLoc = Tok.getLocation();
3637     SourceLocation ELoc = ConsumeToken();
3638     ExprResult Tail = ParseAssignmentExpression();
3639     Tail =
3640         Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
3641     if (Tail.isUsable())
3642       Data.DepModOrTailExpr = Tail.get();
3643     else
3644       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3645                 StopBeforeMatch);
3646   }
3647 
3648   // Parse ')'.
3649   Data.RLoc = Tok.getLocation();
3650   if (!T.consumeClose())
3651     Data.RLoc = T.getCloseLocation();
3652   // Exit from scope when the iterator is used in depend clause.
3653   if (HasIterator)
3654     ExitScope();
3655   return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
3656          (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId ||
3657          IsInvalidMapperModifier;
3658 }
3659 
3660 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
3661 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
3662 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
3663 ///
3664 ///    private-clause:
3665 ///       'private' '(' list ')'
3666 ///    firstprivate-clause:
3667 ///       'firstprivate' '(' list ')'
3668 ///    lastprivate-clause:
3669 ///       'lastprivate' '(' list ')'
3670 ///    shared-clause:
3671 ///       'shared' '(' list ')'
3672 ///    linear-clause:
3673 ///       'linear' '(' linear-list [ ':' linear-step ] ')'
3674 ///    aligned-clause:
3675 ///       'aligned' '(' list [ ':' alignment ] ')'
3676 ///    reduction-clause:
3677 ///       'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
3678 ///    task_reduction-clause:
3679 ///       'task_reduction' '(' reduction-identifier ':' list ')'
3680 ///    in_reduction-clause:
3681 ///       'in_reduction' '(' reduction-identifier ':' list ')'
3682 ///    copyprivate-clause:
3683 ///       'copyprivate' '(' list ')'
3684 ///    flush-clause:
3685 ///       'flush' '(' list ')'
3686 ///    depend-clause:
3687 ///       'depend' '(' in | out | inout : list | source ')'
3688 ///    map-clause:
3689 ///       'map' '(' [ [ always [,] ] [ close [,] ]
3690 ///          [ mapper '(' mapper-identifier ')' [,] ]
3691 ///          to | from | tofrom | alloc | release | delete ':' ] list ')';
3692 ///    to-clause:
3693 ///       'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
3694 ///    from-clause:
3695 ///       'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
3696 ///    use_device_ptr-clause:
3697 ///       'use_device_ptr' '(' list ')'
3698 ///    use_device_addr-clause:
3699 ///       'use_device_addr' '(' list ')'
3700 ///    is_device_ptr-clause:
3701 ///       'is_device_ptr' '(' list ')'
3702 ///    allocate-clause:
3703 ///       'allocate' '(' [ allocator ':' ] list ')'
3704 ///    nontemporal-clause:
3705 ///       'nontemporal' '(' list ')'
3706 ///    inclusive-clause:
3707 ///       'inclusive' '(' list ')'
3708 ///    exclusive-clause:
3709 ///       'exclusive' '(' list ')'
3710 ///
3711 /// For 'linear' clause linear-list may have the following forms:
3712 ///  list
3713 ///  modifier(list)
3714 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,OpenMPClauseKind Kind,bool ParseOnly)3715 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
3716                                             OpenMPClauseKind Kind,
3717                                             bool ParseOnly) {
3718   SourceLocation Loc = Tok.getLocation();
3719   SourceLocation LOpen = ConsumeToken();
3720   SmallVector<Expr *, 4> Vars;
3721   OpenMPVarListDataTy Data;
3722 
3723   if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
3724     return nullptr;
3725 
3726   if (ParseOnly)
3727     return nullptr;
3728   OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
3729   return Actions.ActOnOpenMPVarListClause(
3730       Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc,
3731       Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
3732       Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
3733       Data.IsMapTypeImplicit, Data.ExtraModifierLoc, Data.MotionModifiers,
3734       Data.MotionModifiersLoc);
3735 }
3736