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