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