xref: /freebsd/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric /// \file
9*0b57cec5SDimitry Andric /// This file implements parsing of all OpenMP directives and clauses.
10*0b57cec5SDimitry Andric ///
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
14*0b57cec5SDimitry Andric #include "clang/AST/StmtOpenMP.h"
15*0b57cec5SDimitry Andric #include "clang/Parse/ParseDiagnostic.h"
16*0b57cec5SDimitry Andric #include "clang/Parse/Parser.h"
17*0b57cec5SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h"
18*0b57cec5SDimitry Andric #include "clang/Sema/Scope.h"
19*0b57cec5SDimitry Andric #include "llvm/ADT/PointerIntPair.h"
20*0b57cec5SDimitry Andric 
21*0b57cec5SDimitry Andric using namespace clang;
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
24*0b57cec5SDimitry Andric // OpenMP declarative directives.
25*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric namespace {
28*0b57cec5SDimitry Andric enum OpenMPDirectiveKindEx {
29*0b57cec5SDimitry Andric   OMPD_cancellation = OMPD_unknown + 1,
30*0b57cec5SDimitry Andric   OMPD_data,
31*0b57cec5SDimitry Andric   OMPD_declare,
32*0b57cec5SDimitry Andric   OMPD_end,
33*0b57cec5SDimitry Andric   OMPD_end_declare,
34*0b57cec5SDimitry Andric   OMPD_enter,
35*0b57cec5SDimitry Andric   OMPD_exit,
36*0b57cec5SDimitry Andric   OMPD_point,
37*0b57cec5SDimitry Andric   OMPD_reduction,
38*0b57cec5SDimitry Andric   OMPD_target_enter,
39*0b57cec5SDimitry Andric   OMPD_target_exit,
40*0b57cec5SDimitry Andric   OMPD_update,
41*0b57cec5SDimitry Andric   OMPD_distribute_parallel,
42*0b57cec5SDimitry Andric   OMPD_teams_distribute_parallel,
43*0b57cec5SDimitry Andric   OMPD_target_teams_distribute_parallel,
44*0b57cec5SDimitry Andric   OMPD_mapper,
45*0b57cec5SDimitry Andric };
46*0b57cec5SDimitry Andric 
47*0b57cec5SDimitry Andric class DeclDirectiveListParserHelper final {
48*0b57cec5SDimitry Andric   SmallVector<Expr *, 4> Identifiers;
49*0b57cec5SDimitry Andric   Parser *P;
50*0b57cec5SDimitry Andric   OpenMPDirectiveKind Kind;
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric public:
53*0b57cec5SDimitry Andric   DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
54*0b57cec5SDimitry Andric       : P(P), Kind(Kind) {}
55*0b57cec5SDimitry Andric   void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
56*0b57cec5SDimitry Andric     ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
57*0b57cec5SDimitry Andric         P->getCurScope(), SS, NameInfo, Kind);
58*0b57cec5SDimitry Andric     if (Res.isUsable())
59*0b57cec5SDimitry Andric       Identifiers.push_back(Res.get());
60*0b57cec5SDimitry Andric   }
61*0b57cec5SDimitry Andric   llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
62*0b57cec5SDimitry Andric };
63*0b57cec5SDimitry Andric } // namespace
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric // Map token string to extended OMP token kind that are
66*0b57cec5SDimitry Andric // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
67*0b57cec5SDimitry Andric static unsigned getOpenMPDirectiveKindEx(StringRef S) {
68*0b57cec5SDimitry Andric   auto DKind = getOpenMPDirectiveKind(S);
69*0b57cec5SDimitry Andric   if (DKind != OMPD_unknown)
70*0b57cec5SDimitry Andric     return DKind;
71*0b57cec5SDimitry Andric 
72*0b57cec5SDimitry Andric   return llvm::StringSwitch<unsigned>(S)
73*0b57cec5SDimitry Andric       .Case("cancellation", OMPD_cancellation)
74*0b57cec5SDimitry Andric       .Case("data", OMPD_data)
75*0b57cec5SDimitry Andric       .Case("declare", OMPD_declare)
76*0b57cec5SDimitry Andric       .Case("end", OMPD_end)
77*0b57cec5SDimitry Andric       .Case("enter", OMPD_enter)
78*0b57cec5SDimitry Andric       .Case("exit", OMPD_exit)
79*0b57cec5SDimitry Andric       .Case("point", OMPD_point)
80*0b57cec5SDimitry Andric       .Case("reduction", OMPD_reduction)
81*0b57cec5SDimitry Andric       .Case("update", OMPD_update)
82*0b57cec5SDimitry Andric       .Case("mapper", OMPD_mapper)
83*0b57cec5SDimitry Andric       .Default(OMPD_unknown);
84*0b57cec5SDimitry Andric }
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
87*0b57cec5SDimitry Andric   // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
88*0b57cec5SDimitry Andric   // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
89*0b57cec5SDimitry Andric   // TODO: add other combined directives in topological order.
90*0b57cec5SDimitry Andric   static const unsigned F[][3] = {
91*0b57cec5SDimitry Andric       {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
92*0b57cec5SDimitry Andric       {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
93*0b57cec5SDimitry Andric       {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
94*0b57cec5SDimitry Andric       {OMPD_declare, OMPD_simd, OMPD_declare_simd},
95*0b57cec5SDimitry Andric       {OMPD_declare, OMPD_target, OMPD_declare_target},
96*0b57cec5SDimitry Andric       {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
97*0b57cec5SDimitry Andric       {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
98*0b57cec5SDimitry Andric       {OMPD_distribute_parallel_for, OMPD_simd,
99*0b57cec5SDimitry Andric        OMPD_distribute_parallel_for_simd},
100*0b57cec5SDimitry Andric       {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
101*0b57cec5SDimitry Andric       {OMPD_end, OMPD_declare, OMPD_end_declare},
102*0b57cec5SDimitry Andric       {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
103*0b57cec5SDimitry Andric       {OMPD_target, OMPD_data, OMPD_target_data},
104*0b57cec5SDimitry Andric       {OMPD_target, OMPD_enter, OMPD_target_enter},
105*0b57cec5SDimitry Andric       {OMPD_target, OMPD_exit, OMPD_target_exit},
106*0b57cec5SDimitry Andric       {OMPD_target, OMPD_update, OMPD_target_update},
107*0b57cec5SDimitry Andric       {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
108*0b57cec5SDimitry Andric       {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
109*0b57cec5SDimitry Andric       {OMPD_for, OMPD_simd, OMPD_for_simd},
110*0b57cec5SDimitry Andric       {OMPD_parallel, OMPD_for, OMPD_parallel_for},
111*0b57cec5SDimitry Andric       {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
112*0b57cec5SDimitry Andric       {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
113*0b57cec5SDimitry Andric       {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
114*0b57cec5SDimitry Andric       {OMPD_target, OMPD_parallel, OMPD_target_parallel},
115*0b57cec5SDimitry Andric       {OMPD_target, OMPD_simd, OMPD_target_simd},
116*0b57cec5SDimitry Andric       {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
117*0b57cec5SDimitry Andric       {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
118*0b57cec5SDimitry Andric       {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
119*0b57cec5SDimitry Andric       {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
120*0b57cec5SDimitry Andric       {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
121*0b57cec5SDimitry Andric       {OMPD_teams_distribute_parallel, OMPD_for,
122*0b57cec5SDimitry Andric        OMPD_teams_distribute_parallel_for},
123*0b57cec5SDimitry Andric       {OMPD_teams_distribute_parallel_for, OMPD_simd,
124*0b57cec5SDimitry Andric        OMPD_teams_distribute_parallel_for_simd},
125*0b57cec5SDimitry Andric       {OMPD_target, OMPD_teams, OMPD_target_teams},
126*0b57cec5SDimitry Andric       {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
127*0b57cec5SDimitry Andric       {OMPD_target_teams_distribute, OMPD_parallel,
128*0b57cec5SDimitry Andric        OMPD_target_teams_distribute_parallel},
129*0b57cec5SDimitry Andric       {OMPD_target_teams_distribute, OMPD_simd,
130*0b57cec5SDimitry Andric        OMPD_target_teams_distribute_simd},
131*0b57cec5SDimitry Andric       {OMPD_target_teams_distribute_parallel, OMPD_for,
132*0b57cec5SDimitry Andric        OMPD_target_teams_distribute_parallel_for},
133*0b57cec5SDimitry Andric       {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
134*0b57cec5SDimitry Andric        OMPD_target_teams_distribute_parallel_for_simd}};
135*0b57cec5SDimitry Andric   enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
136*0b57cec5SDimitry Andric   Token Tok = P.getCurToken();
137*0b57cec5SDimitry Andric   unsigned DKind =
138*0b57cec5SDimitry Andric       Tok.isAnnotation()
139*0b57cec5SDimitry Andric           ? static_cast<unsigned>(OMPD_unknown)
140*0b57cec5SDimitry Andric           : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
141*0b57cec5SDimitry Andric   if (DKind == OMPD_unknown)
142*0b57cec5SDimitry Andric     return OMPD_unknown;
143*0b57cec5SDimitry Andric 
144*0b57cec5SDimitry Andric   for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
145*0b57cec5SDimitry Andric     if (DKind != F[I][0])
146*0b57cec5SDimitry Andric       continue;
147*0b57cec5SDimitry Andric 
148*0b57cec5SDimitry Andric     Tok = P.getPreprocessor().LookAhead(0);
149*0b57cec5SDimitry Andric     unsigned SDKind =
150*0b57cec5SDimitry Andric         Tok.isAnnotation()
151*0b57cec5SDimitry Andric             ? static_cast<unsigned>(OMPD_unknown)
152*0b57cec5SDimitry Andric             : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
153*0b57cec5SDimitry Andric     if (SDKind == OMPD_unknown)
154*0b57cec5SDimitry Andric       continue;
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric     if (SDKind == F[I][1]) {
157*0b57cec5SDimitry Andric       P.ConsumeToken();
158*0b57cec5SDimitry Andric       DKind = F[I][2];
159*0b57cec5SDimitry Andric     }
160*0b57cec5SDimitry Andric   }
161*0b57cec5SDimitry Andric   return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
162*0b57cec5SDimitry Andric                               : OMPD_unknown;
163*0b57cec5SDimitry Andric }
164*0b57cec5SDimitry Andric 
165*0b57cec5SDimitry Andric static DeclarationName parseOpenMPReductionId(Parser &P) {
166*0b57cec5SDimitry Andric   Token Tok = P.getCurToken();
167*0b57cec5SDimitry Andric   Sema &Actions = P.getActions();
168*0b57cec5SDimitry Andric   OverloadedOperatorKind OOK = OO_None;
169*0b57cec5SDimitry Andric   // Allow to use 'operator' keyword for C++ operators
170*0b57cec5SDimitry Andric   bool WithOperator = false;
171*0b57cec5SDimitry Andric   if (Tok.is(tok::kw_operator)) {
172*0b57cec5SDimitry Andric     P.ConsumeToken();
173*0b57cec5SDimitry Andric     Tok = P.getCurToken();
174*0b57cec5SDimitry Andric     WithOperator = true;
175*0b57cec5SDimitry Andric   }
176*0b57cec5SDimitry Andric   switch (Tok.getKind()) {
177*0b57cec5SDimitry Andric   case tok::plus: // '+'
178*0b57cec5SDimitry Andric     OOK = OO_Plus;
179*0b57cec5SDimitry Andric     break;
180*0b57cec5SDimitry Andric   case tok::minus: // '-'
181*0b57cec5SDimitry Andric     OOK = OO_Minus;
182*0b57cec5SDimitry Andric     break;
183*0b57cec5SDimitry Andric   case tok::star: // '*'
184*0b57cec5SDimitry Andric     OOK = OO_Star;
185*0b57cec5SDimitry Andric     break;
186*0b57cec5SDimitry Andric   case tok::amp: // '&'
187*0b57cec5SDimitry Andric     OOK = OO_Amp;
188*0b57cec5SDimitry Andric     break;
189*0b57cec5SDimitry Andric   case tok::pipe: // '|'
190*0b57cec5SDimitry Andric     OOK = OO_Pipe;
191*0b57cec5SDimitry Andric     break;
192*0b57cec5SDimitry Andric   case tok::caret: // '^'
193*0b57cec5SDimitry Andric     OOK = OO_Caret;
194*0b57cec5SDimitry Andric     break;
195*0b57cec5SDimitry Andric   case tok::ampamp: // '&&'
196*0b57cec5SDimitry Andric     OOK = OO_AmpAmp;
197*0b57cec5SDimitry Andric     break;
198*0b57cec5SDimitry Andric   case tok::pipepipe: // '||'
199*0b57cec5SDimitry Andric     OOK = OO_PipePipe;
200*0b57cec5SDimitry Andric     break;
201*0b57cec5SDimitry Andric   case tok::identifier: // identifier
202*0b57cec5SDimitry Andric     if (!WithOperator)
203*0b57cec5SDimitry Andric       break;
204*0b57cec5SDimitry Andric     LLVM_FALLTHROUGH;
205*0b57cec5SDimitry Andric   default:
206*0b57cec5SDimitry Andric     P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
207*0b57cec5SDimitry Andric     P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
208*0b57cec5SDimitry Andric                 Parser::StopBeforeMatch);
209*0b57cec5SDimitry Andric     return DeclarationName();
210*0b57cec5SDimitry Andric   }
211*0b57cec5SDimitry Andric   P.ConsumeToken();
212*0b57cec5SDimitry Andric   auto &DeclNames = Actions.getASTContext().DeclarationNames;
213*0b57cec5SDimitry Andric   return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
214*0b57cec5SDimitry Andric                         : DeclNames.getCXXOperatorName(OOK);
215*0b57cec5SDimitry Andric }
216*0b57cec5SDimitry Andric 
217*0b57cec5SDimitry Andric /// Parse 'omp declare reduction' construct.
218*0b57cec5SDimitry Andric ///
219*0b57cec5SDimitry Andric ///       declare-reduction-directive:
220*0b57cec5SDimitry Andric ///        annot_pragma_openmp 'declare' 'reduction'
221*0b57cec5SDimitry Andric ///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
222*0b57cec5SDimitry Andric ///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
223*0b57cec5SDimitry Andric ///        annot_pragma_openmp_end
224*0b57cec5SDimitry Andric /// <reduction_id> is either a base language identifier or one of the following
225*0b57cec5SDimitry Andric /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
226*0b57cec5SDimitry Andric ///
227*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy
228*0b57cec5SDimitry Andric Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
229*0b57cec5SDimitry Andric   // Parse '('.
230*0b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
231*0b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
232*0b57cec5SDimitry Andric                          getOpenMPDirectiveName(OMPD_declare_reduction))) {
233*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
234*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
235*0b57cec5SDimitry Andric   }
236*0b57cec5SDimitry Andric 
237*0b57cec5SDimitry Andric   DeclarationName Name = parseOpenMPReductionId(*this);
238*0b57cec5SDimitry Andric   if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
239*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
240*0b57cec5SDimitry Andric 
241*0b57cec5SDimitry Andric   // Consume ':'.
242*0b57cec5SDimitry Andric   bool IsCorrect = !ExpectAndConsume(tok::colon);
243*0b57cec5SDimitry Andric 
244*0b57cec5SDimitry Andric   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
245*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
246*0b57cec5SDimitry Andric 
247*0b57cec5SDimitry Andric   IsCorrect = IsCorrect && !Name.isEmpty();
248*0b57cec5SDimitry Andric 
249*0b57cec5SDimitry Andric   if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
250*0b57cec5SDimitry Andric     Diag(Tok.getLocation(), diag::err_expected_type);
251*0b57cec5SDimitry Andric     IsCorrect = false;
252*0b57cec5SDimitry Andric   }
253*0b57cec5SDimitry Andric 
254*0b57cec5SDimitry Andric   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
255*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
256*0b57cec5SDimitry Andric 
257*0b57cec5SDimitry Andric   SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
258*0b57cec5SDimitry Andric   // Parse list of types until ':' token.
259*0b57cec5SDimitry Andric   do {
260*0b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
261*0b57cec5SDimitry Andric     SourceRange Range;
262*0b57cec5SDimitry Andric     TypeResult TR =
263*0b57cec5SDimitry Andric         ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
264*0b57cec5SDimitry Andric     if (TR.isUsable()) {
265*0b57cec5SDimitry Andric       QualType ReductionType =
266*0b57cec5SDimitry Andric           Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
267*0b57cec5SDimitry Andric       if (!ReductionType.isNull()) {
268*0b57cec5SDimitry Andric         ReductionTypes.push_back(
269*0b57cec5SDimitry Andric             std::make_pair(ReductionType, Range.getBegin()));
270*0b57cec5SDimitry Andric       }
271*0b57cec5SDimitry Andric     } else {
272*0b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
273*0b57cec5SDimitry Andric                 StopBeforeMatch);
274*0b57cec5SDimitry Andric     }
275*0b57cec5SDimitry Andric 
276*0b57cec5SDimitry Andric     if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
277*0b57cec5SDimitry Andric       break;
278*0b57cec5SDimitry Andric 
279*0b57cec5SDimitry Andric     // Consume ','.
280*0b57cec5SDimitry Andric     if (ExpectAndConsume(tok::comma)) {
281*0b57cec5SDimitry Andric       IsCorrect = false;
282*0b57cec5SDimitry Andric       if (Tok.is(tok::annot_pragma_openmp_end)) {
283*0b57cec5SDimitry Andric         Diag(Tok.getLocation(), diag::err_expected_type);
284*0b57cec5SDimitry Andric         return DeclGroupPtrTy();
285*0b57cec5SDimitry Andric       }
286*0b57cec5SDimitry Andric     }
287*0b57cec5SDimitry Andric   } while (Tok.isNot(tok::annot_pragma_openmp_end));
288*0b57cec5SDimitry Andric 
289*0b57cec5SDimitry Andric   if (ReductionTypes.empty()) {
290*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
291*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
292*0b57cec5SDimitry Andric   }
293*0b57cec5SDimitry Andric 
294*0b57cec5SDimitry Andric   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
295*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
296*0b57cec5SDimitry Andric 
297*0b57cec5SDimitry Andric   // Consume ':'.
298*0b57cec5SDimitry Andric   if (ExpectAndConsume(tok::colon))
299*0b57cec5SDimitry Andric     IsCorrect = false;
300*0b57cec5SDimitry Andric 
301*0b57cec5SDimitry Andric   if (Tok.is(tok::annot_pragma_openmp_end)) {
302*0b57cec5SDimitry Andric     Diag(Tok.getLocation(), diag::err_expected_expression);
303*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
304*0b57cec5SDimitry Andric   }
305*0b57cec5SDimitry Andric 
306*0b57cec5SDimitry Andric   DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
307*0b57cec5SDimitry Andric       getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
308*0b57cec5SDimitry Andric 
309*0b57cec5SDimitry Andric   // Parse <combiner> expression and then parse initializer if any for each
310*0b57cec5SDimitry Andric   // correct type.
311*0b57cec5SDimitry Andric   unsigned I = 0, E = ReductionTypes.size();
312*0b57cec5SDimitry Andric   for (Decl *D : DRD.get()) {
313*0b57cec5SDimitry Andric     TentativeParsingAction TPA(*this);
314*0b57cec5SDimitry Andric     ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
315*0b57cec5SDimitry Andric                                     Scope::CompoundStmtScope |
316*0b57cec5SDimitry Andric                                     Scope::OpenMPDirectiveScope);
317*0b57cec5SDimitry Andric     // Parse <combiner> expression.
318*0b57cec5SDimitry Andric     Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
319*0b57cec5SDimitry Andric     ExprResult CombinerResult =
320*0b57cec5SDimitry Andric         Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
321*0b57cec5SDimitry Andric                                     D->getLocation(), /*DiscardedValue*/ false);
322*0b57cec5SDimitry Andric     Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
323*0b57cec5SDimitry Andric 
324*0b57cec5SDimitry Andric     if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
325*0b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end)) {
326*0b57cec5SDimitry Andric       TPA.Commit();
327*0b57cec5SDimitry Andric       IsCorrect = false;
328*0b57cec5SDimitry Andric       break;
329*0b57cec5SDimitry Andric     }
330*0b57cec5SDimitry Andric     IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
331*0b57cec5SDimitry Andric     ExprResult InitializerResult;
332*0b57cec5SDimitry Andric     if (Tok.isNot(tok::annot_pragma_openmp_end)) {
333*0b57cec5SDimitry Andric       // Parse <initializer> expression.
334*0b57cec5SDimitry Andric       if (Tok.is(tok::identifier) &&
335*0b57cec5SDimitry Andric           Tok.getIdentifierInfo()->isStr("initializer")) {
336*0b57cec5SDimitry Andric         ConsumeToken();
337*0b57cec5SDimitry Andric       } else {
338*0b57cec5SDimitry Andric         Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
339*0b57cec5SDimitry Andric         TPA.Commit();
340*0b57cec5SDimitry Andric         IsCorrect = false;
341*0b57cec5SDimitry Andric         break;
342*0b57cec5SDimitry Andric       }
343*0b57cec5SDimitry Andric       // Parse '('.
344*0b57cec5SDimitry Andric       BalancedDelimiterTracker T(*this, tok::l_paren,
345*0b57cec5SDimitry Andric                                  tok::annot_pragma_openmp_end);
346*0b57cec5SDimitry Andric       IsCorrect =
347*0b57cec5SDimitry Andric           !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
348*0b57cec5SDimitry Andric           IsCorrect;
349*0b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
350*0b57cec5SDimitry Andric         ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
351*0b57cec5SDimitry Andric                                         Scope::CompoundStmtScope |
352*0b57cec5SDimitry Andric                                         Scope::OpenMPDirectiveScope);
353*0b57cec5SDimitry Andric         // Parse expression.
354*0b57cec5SDimitry Andric         VarDecl *OmpPrivParm =
355*0b57cec5SDimitry Andric             Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
356*0b57cec5SDimitry Andric                                                                 D);
357*0b57cec5SDimitry Andric         // Check if initializer is omp_priv <init_expr> or something else.
358*0b57cec5SDimitry Andric         if (Tok.is(tok::identifier) &&
359*0b57cec5SDimitry Andric             Tok.getIdentifierInfo()->isStr("omp_priv")) {
360*0b57cec5SDimitry Andric           if (Actions.getLangOpts().CPlusPlus) {
361*0b57cec5SDimitry Andric             InitializerResult = Actions.ActOnFinishFullExpr(
362*0b57cec5SDimitry Andric                 ParseAssignmentExpression().get(), D->getLocation(),
363*0b57cec5SDimitry Andric                 /*DiscardedValue*/ false);
364*0b57cec5SDimitry Andric           } else {
365*0b57cec5SDimitry Andric             ConsumeToken();
366*0b57cec5SDimitry Andric             ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
367*0b57cec5SDimitry Andric           }
368*0b57cec5SDimitry Andric         } else {
369*0b57cec5SDimitry Andric           InitializerResult = Actions.ActOnFinishFullExpr(
370*0b57cec5SDimitry Andric               ParseAssignmentExpression().get(), D->getLocation(),
371*0b57cec5SDimitry Andric               /*DiscardedValue*/ false);
372*0b57cec5SDimitry Andric         }
373*0b57cec5SDimitry Andric         Actions.ActOnOpenMPDeclareReductionInitializerEnd(
374*0b57cec5SDimitry Andric             D, InitializerResult.get(), OmpPrivParm);
375*0b57cec5SDimitry Andric         if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
376*0b57cec5SDimitry Andric             Tok.isNot(tok::annot_pragma_openmp_end)) {
377*0b57cec5SDimitry Andric           TPA.Commit();
378*0b57cec5SDimitry Andric           IsCorrect = false;
379*0b57cec5SDimitry Andric           break;
380*0b57cec5SDimitry Andric         }
381*0b57cec5SDimitry Andric         IsCorrect =
382*0b57cec5SDimitry Andric             !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
383*0b57cec5SDimitry Andric       }
384*0b57cec5SDimitry Andric     }
385*0b57cec5SDimitry Andric 
386*0b57cec5SDimitry Andric     ++I;
387*0b57cec5SDimitry Andric     // Revert parsing if not the last type, otherwise accept it, we're done with
388*0b57cec5SDimitry Andric     // parsing.
389*0b57cec5SDimitry Andric     if (I != E)
390*0b57cec5SDimitry Andric       TPA.Revert();
391*0b57cec5SDimitry Andric     else
392*0b57cec5SDimitry Andric       TPA.Commit();
393*0b57cec5SDimitry Andric   }
394*0b57cec5SDimitry Andric   return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
395*0b57cec5SDimitry Andric                                                          IsCorrect);
396*0b57cec5SDimitry Andric }
397*0b57cec5SDimitry Andric 
398*0b57cec5SDimitry Andric void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
399*0b57cec5SDimitry Andric   // Parse declarator '=' initializer.
400*0b57cec5SDimitry Andric   // If a '==' or '+=' is found, suggest a fixit to '='.
401*0b57cec5SDimitry Andric   if (isTokenEqualOrEqualTypo()) {
402*0b57cec5SDimitry Andric     ConsumeToken();
403*0b57cec5SDimitry Andric 
404*0b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
405*0b57cec5SDimitry Andric       Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
406*0b57cec5SDimitry Andric       Actions.FinalizeDeclaration(OmpPrivParm);
407*0b57cec5SDimitry Andric       cutOffParsing();
408*0b57cec5SDimitry Andric       return;
409*0b57cec5SDimitry Andric     }
410*0b57cec5SDimitry Andric 
411*0b57cec5SDimitry Andric     ExprResult Init(ParseInitializer());
412*0b57cec5SDimitry Andric 
413*0b57cec5SDimitry Andric     if (Init.isInvalid()) {
414*0b57cec5SDimitry Andric       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
415*0b57cec5SDimitry Andric       Actions.ActOnInitializerError(OmpPrivParm);
416*0b57cec5SDimitry Andric     } else {
417*0b57cec5SDimitry Andric       Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
418*0b57cec5SDimitry Andric                                    /*DirectInit=*/false);
419*0b57cec5SDimitry Andric     }
420*0b57cec5SDimitry Andric   } else if (Tok.is(tok::l_paren)) {
421*0b57cec5SDimitry Andric     // Parse C++ direct initializer: '(' expression-list ')'
422*0b57cec5SDimitry Andric     BalancedDelimiterTracker T(*this, tok::l_paren);
423*0b57cec5SDimitry Andric     T.consumeOpen();
424*0b57cec5SDimitry Andric 
425*0b57cec5SDimitry Andric     ExprVector Exprs;
426*0b57cec5SDimitry Andric     CommaLocsTy CommaLocs;
427*0b57cec5SDimitry Andric 
428*0b57cec5SDimitry Andric     SourceLocation LParLoc = T.getOpenLocation();
429*0b57cec5SDimitry Andric     auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
430*0b57cec5SDimitry Andric       QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
431*0b57cec5SDimitry Andric           getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
432*0b57cec5SDimitry Andric           OmpPrivParm->getLocation(), Exprs, LParLoc);
433*0b57cec5SDimitry Andric       CalledSignatureHelp = true;
434*0b57cec5SDimitry Andric       return PreferredType;
435*0b57cec5SDimitry Andric     };
436*0b57cec5SDimitry Andric     if (ParseExpressionList(Exprs, CommaLocs, [&] {
437*0b57cec5SDimitry Andric           PreferredType.enterFunctionArgument(Tok.getLocation(),
438*0b57cec5SDimitry Andric                                               RunSignatureHelp);
439*0b57cec5SDimitry Andric         })) {
440*0b57cec5SDimitry Andric       if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
441*0b57cec5SDimitry Andric         RunSignatureHelp();
442*0b57cec5SDimitry Andric       Actions.ActOnInitializerError(OmpPrivParm);
443*0b57cec5SDimitry Andric       SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
444*0b57cec5SDimitry Andric     } else {
445*0b57cec5SDimitry Andric       // Match the ')'.
446*0b57cec5SDimitry Andric       SourceLocation RLoc = Tok.getLocation();
447*0b57cec5SDimitry Andric       if (!T.consumeClose())
448*0b57cec5SDimitry Andric         RLoc = T.getCloseLocation();
449*0b57cec5SDimitry Andric 
450*0b57cec5SDimitry Andric       assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
451*0b57cec5SDimitry Andric              "Unexpected number of commas!");
452*0b57cec5SDimitry Andric 
453*0b57cec5SDimitry Andric       ExprResult Initializer =
454*0b57cec5SDimitry Andric           Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
455*0b57cec5SDimitry Andric       Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
456*0b57cec5SDimitry Andric                                    /*DirectInit=*/true);
457*0b57cec5SDimitry Andric     }
458*0b57cec5SDimitry Andric   } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
459*0b57cec5SDimitry Andric     // Parse C++0x braced-init-list.
460*0b57cec5SDimitry Andric     Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
461*0b57cec5SDimitry Andric 
462*0b57cec5SDimitry Andric     ExprResult Init(ParseBraceInitializer());
463*0b57cec5SDimitry Andric 
464*0b57cec5SDimitry Andric     if (Init.isInvalid()) {
465*0b57cec5SDimitry Andric       Actions.ActOnInitializerError(OmpPrivParm);
466*0b57cec5SDimitry Andric     } else {
467*0b57cec5SDimitry Andric       Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
468*0b57cec5SDimitry Andric                                    /*DirectInit=*/true);
469*0b57cec5SDimitry Andric     }
470*0b57cec5SDimitry Andric   } else {
471*0b57cec5SDimitry Andric     Actions.ActOnUninitializedDecl(OmpPrivParm);
472*0b57cec5SDimitry Andric   }
473*0b57cec5SDimitry Andric }
474*0b57cec5SDimitry Andric 
475*0b57cec5SDimitry Andric /// Parses 'omp declare mapper' directive.
476*0b57cec5SDimitry Andric ///
477*0b57cec5SDimitry Andric ///       declare-mapper-directive:
478*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
479*0b57cec5SDimitry Andric ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
480*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
481*0b57cec5SDimitry Andric /// <mapper-identifier> and <var> are base language identifiers.
482*0b57cec5SDimitry Andric ///
483*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy
484*0b57cec5SDimitry Andric Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
485*0b57cec5SDimitry Andric   bool IsCorrect = true;
486*0b57cec5SDimitry Andric   // Parse '('
487*0b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
488*0b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
489*0b57cec5SDimitry Andric                          getOpenMPDirectiveName(OMPD_declare_mapper))) {
490*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
491*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
492*0b57cec5SDimitry Andric   }
493*0b57cec5SDimitry Andric 
494*0b57cec5SDimitry Andric   // Parse <mapper-identifier>
495*0b57cec5SDimitry Andric   auto &DeclNames = Actions.getASTContext().DeclarationNames;
496*0b57cec5SDimitry Andric   DeclarationName MapperId;
497*0b57cec5SDimitry Andric   if (PP.LookAhead(0).is(tok::colon)) {
498*0b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
499*0b57cec5SDimitry Andric       Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
500*0b57cec5SDimitry Andric       IsCorrect = false;
501*0b57cec5SDimitry Andric     } else {
502*0b57cec5SDimitry Andric       MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
503*0b57cec5SDimitry Andric     }
504*0b57cec5SDimitry Andric     ConsumeToken();
505*0b57cec5SDimitry Andric     // Consume ':'.
506*0b57cec5SDimitry Andric     ExpectAndConsume(tok::colon);
507*0b57cec5SDimitry Andric   } else {
508*0b57cec5SDimitry Andric     // If no mapper identifier is provided, its name is "default" by default
509*0b57cec5SDimitry Andric     MapperId =
510*0b57cec5SDimitry Andric         DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
511*0b57cec5SDimitry Andric   }
512*0b57cec5SDimitry Andric 
513*0b57cec5SDimitry Andric   if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
514*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
515*0b57cec5SDimitry Andric 
516*0b57cec5SDimitry Andric   // Parse <type> <var>
517*0b57cec5SDimitry Andric   DeclarationName VName;
518*0b57cec5SDimitry Andric   QualType MapperType;
519*0b57cec5SDimitry Andric   SourceRange Range;
520*0b57cec5SDimitry Andric   TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
521*0b57cec5SDimitry Andric   if (ParsedType.isUsable())
522*0b57cec5SDimitry Andric     MapperType =
523*0b57cec5SDimitry Andric         Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
524*0b57cec5SDimitry Andric   if (MapperType.isNull())
525*0b57cec5SDimitry Andric     IsCorrect = false;
526*0b57cec5SDimitry Andric   if (!IsCorrect) {
527*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
528*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
529*0b57cec5SDimitry Andric   }
530*0b57cec5SDimitry Andric 
531*0b57cec5SDimitry Andric   // Consume ')'.
532*0b57cec5SDimitry Andric   IsCorrect &= !T.consumeClose();
533*0b57cec5SDimitry Andric   if (!IsCorrect) {
534*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
535*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
536*0b57cec5SDimitry Andric   }
537*0b57cec5SDimitry Andric 
538*0b57cec5SDimitry Andric   // Enter scope.
539*0b57cec5SDimitry Andric   OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
540*0b57cec5SDimitry Andric       getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
541*0b57cec5SDimitry Andric       Range.getBegin(), VName, AS);
542*0b57cec5SDimitry Andric   DeclarationNameInfo DirName;
543*0b57cec5SDimitry Andric   SourceLocation Loc = Tok.getLocation();
544*0b57cec5SDimitry Andric   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
545*0b57cec5SDimitry Andric                         Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
546*0b57cec5SDimitry Andric   ParseScope OMPDirectiveScope(this, ScopeFlags);
547*0b57cec5SDimitry Andric   Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
548*0b57cec5SDimitry Andric 
549*0b57cec5SDimitry Andric   // Add the mapper variable declaration.
550*0b57cec5SDimitry Andric   Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
551*0b57cec5SDimitry Andric       DMD, getCurScope(), MapperType, Range.getBegin(), VName);
552*0b57cec5SDimitry Andric 
553*0b57cec5SDimitry Andric   // Parse map clauses.
554*0b57cec5SDimitry Andric   SmallVector<OMPClause *, 6> Clauses;
555*0b57cec5SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
556*0b57cec5SDimitry Andric     OpenMPClauseKind CKind = Tok.isAnnotation()
557*0b57cec5SDimitry Andric                                  ? OMPC_unknown
558*0b57cec5SDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
559*0b57cec5SDimitry Andric     Actions.StartOpenMPClause(CKind);
560*0b57cec5SDimitry Andric     OMPClause *Clause =
561*0b57cec5SDimitry Andric         ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
562*0b57cec5SDimitry Andric     if (Clause)
563*0b57cec5SDimitry Andric       Clauses.push_back(Clause);
564*0b57cec5SDimitry Andric     else
565*0b57cec5SDimitry Andric       IsCorrect = false;
566*0b57cec5SDimitry Andric     // Skip ',' if any.
567*0b57cec5SDimitry Andric     if (Tok.is(tok::comma))
568*0b57cec5SDimitry Andric       ConsumeToken();
569*0b57cec5SDimitry Andric     Actions.EndOpenMPClause();
570*0b57cec5SDimitry Andric   }
571*0b57cec5SDimitry Andric   if (Clauses.empty()) {
572*0b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_expected_clause)
573*0b57cec5SDimitry Andric         << getOpenMPDirectiveName(OMPD_declare_mapper);
574*0b57cec5SDimitry Andric     IsCorrect = false;
575*0b57cec5SDimitry Andric   }
576*0b57cec5SDimitry Andric 
577*0b57cec5SDimitry Andric   // Exit scope.
578*0b57cec5SDimitry Andric   Actions.EndOpenMPDSABlock(nullptr);
579*0b57cec5SDimitry Andric   OMPDirectiveScope.Exit();
580*0b57cec5SDimitry Andric 
581*0b57cec5SDimitry Andric   DeclGroupPtrTy DGP =
582*0b57cec5SDimitry Andric       Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
583*0b57cec5SDimitry Andric   if (!IsCorrect)
584*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
585*0b57cec5SDimitry Andric   return DGP;
586*0b57cec5SDimitry Andric }
587*0b57cec5SDimitry Andric 
588*0b57cec5SDimitry Andric TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
589*0b57cec5SDimitry Andric                                                    DeclarationName &Name,
590*0b57cec5SDimitry Andric                                                    AccessSpecifier AS) {
591*0b57cec5SDimitry Andric   // Parse the common declaration-specifiers piece.
592*0b57cec5SDimitry Andric   Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
593*0b57cec5SDimitry Andric   DeclSpec DS(AttrFactory);
594*0b57cec5SDimitry Andric   ParseSpecifierQualifierList(DS, AS, DSC);
595*0b57cec5SDimitry Andric 
596*0b57cec5SDimitry Andric   // Parse the declarator.
597*0b57cec5SDimitry Andric   DeclaratorContext Context = DeclaratorContext::PrototypeContext;
598*0b57cec5SDimitry Andric   Declarator DeclaratorInfo(DS, Context);
599*0b57cec5SDimitry Andric   ParseDeclarator(DeclaratorInfo);
600*0b57cec5SDimitry Andric   Range = DeclaratorInfo.getSourceRange();
601*0b57cec5SDimitry Andric   if (DeclaratorInfo.getIdentifier() == nullptr) {
602*0b57cec5SDimitry Andric     Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
603*0b57cec5SDimitry Andric     return true;
604*0b57cec5SDimitry Andric   }
605*0b57cec5SDimitry Andric   Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
606*0b57cec5SDimitry Andric 
607*0b57cec5SDimitry Andric   return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
608*0b57cec5SDimitry Andric }
609*0b57cec5SDimitry Andric 
610*0b57cec5SDimitry Andric namespace {
611*0b57cec5SDimitry Andric /// RAII that recreates function context for correct parsing of clauses of
612*0b57cec5SDimitry Andric /// 'declare simd' construct.
613*0b57cec5SDimitry Andric /// OpenMP, 2.8.2 declare simd Construct
614*0b57cec5SDimitry Andric /// The expressions appearing in the clauses of this directive are evaluated in
615*0b57cec5SDimitry Andric /// the scope of the arguments of the function declaration or definition.
616*0b57cec5SDimitry Andric class FNContextRAII final {
617*0b57cec5SDimitry Andric   Parser &P;
618*0b57cec5SDimitry Andric   Sema::CXXThisScopeRAII *ThisScope;
619*0b57cec5SDimitry Andric   Parser::ParseScope *TempScope;
620*0b57cec5SDimitry Andric   Parser::ParseScope *FnScope;
621*0b57cec5SDimitry Andric   bool HasTemplateScope = false;
622*0b57cec5SDimitry Andric   bool HasFunScope = false;
623*0b57cec5SDimitry Andric   FNContextRAII() = delete;
624*0b57cec5SDimitry Andric   FNContextRAII(const FNContextRAII &) = delete;
625*0b57cec5SDimitry Andric   FNContextRAII &operator=(const FNContextRAII &) = delete;
626*0b57cec5SDimitry Andric 
627*0b57cec5SDimitry Andric public:
628*0b57cec5SDimitry Andric   FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
629*0b57cec5SDimitry Andric     Decl *D = *Ptr.get().begin();
630*0b57cec5SDimitry Andric     NamedDecl *ND = dyn_cast<NamedDecl>(D);
631*0b57cec5SDimitry Andric     RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
632*0b57cec5SDimitry Andric     Sema &Actions = P.getActions();
633*0b57cec5SDimitry Andric 
634*0b57cec5SDimitry Andric     // Allow 'this' within late-parsed attributes.
635*0b57cec5SDimitry Andric     ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
636*0b57cec5SDimitry Andric                                            ND && ND->isCXXInstanceMember());
637*0b57cec5SDimitry Andric 
638*0b57cec5SDimitry Andric     // If the Decl is templatized, add template parameters to scope.
639*0b57cec5SDimitry Andric     HasTemplateScope = D->isTemplateDecl();
640*0b57cec5SDimitry Andric     TempScope =
641*0b57cec5SDimitry Andric         new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
642*0b57cec5SDimitry Andric     if (HasTemplateScope)
643*0b57cec5SDimitry Andric       Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
644*0b57cec5SDimitry Andric 
645*0b57cec5SDimitry Andric     // If the Decl is on a function, add function parameters to the scope.
646*0b57cec5SDimitry Andric     HasFunScope = D->isFunctionOrFunctionTemplate();
647*0b57cec5SDimitry Andric     FnScope = new Parser::ParseScope(
648*0b57cec5SDimitry Andric         &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
649*0b57cec5SDimitry Andric         HasFunScope);
650*0b57cec5SDimitry Andric     if (HasFunScope)
651*0b57cec5SDimitry Andric       Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
652*0b57cec5SDimitry Andric   }
653*0b57cec5SDimitry Andric   ~FNContextRAII() {
654*0b57cec5SDimitry Andric     if (HasFunScope) {
655*0b57cec5SDimitry Andric       P.getActions().ActOnExitFunctionContext();
656*0b57cec5SDimitry Andric       FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
657*0b57cec5SDimitry Andric     }
658*0b57cec5SDimitry Andric     if (HasTemplateScope)
659*0b57cec5SDimitry Andric       TempScope->Exit();
660*0b57cec5SDimitry Andric     delete FnScope;
661*0b57cec5SDimitry Andric     delete TempScope;
662*0b57cec5SDimitry Andric     delete ThisScope;
663*0b57cec5SDimitry Andric   }
664*0b57cec5SDimitry Andric };
665*0b57cec5SDimitry Andric } // namespace
666*0b57cec5SDimitry Andric 
667*0b57cec5SDimitry Andric /// Parses clauses for 'declare simd' directive.
668*0b57cec5SDimitry Andric ///    clause:
669*0b57cec5SDimitry Andric ///      'inbranch' | 'notinbranch'
670*0b57cec5SDimitry Andric ///      'simdlen' '(' <expr> ')'
671*0b57cec5SDimitry Andric ///      { 'uniform' '(' <argument_list> ')' }
672*0b57cec5SDimitry Andric ///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
673*0b57cec5SDimitry Andric ///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }
674*0b57cec5SDimitry Andric static bool parseDeclareSimdClauses(
675*0b57cec5SDimitry Andric     Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
676*0b57cec5SDimitry Andric     SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
677*0b57cec5SDimitry Andric     SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
678*0b57cec5SDimitry Andric     SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
679*0b57cec5SDimitry Andric   SourceRange BSRange;
680*0b57cec5SDimitry Andric   const Token &Tok = P.getCurToken();
681*0b57cec5SDimitry Andric   bool IsError = false;
682*0b57cec5SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
683*0b57cec5SDimitry Andric     if (Tok.isNot(tok::identifier))
684*0b57cec5SDimitry Andric       break;
685*0b57cec5SDimitry Andric     OMPDeclareSimdDeclAttr::BranchStateTy Out;
686*0b57cec5SDimitry Andric     IdentifierInfo *II = Tok.getIdentifierInfo();
687*0b57cec5SDimitry Andric     StringRef ClauseName = II->getName();
688*0b57cec5SDimitry Andric     // Parse 'inranch|notinbranch' clauses.
689*0b57cec5SDimitry Andric     if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
690*0b57cec5SDimitry Andric       if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
691*0b57cec5SDimitry Andric         P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
692*0b57cec5SDimitry Andric             << ClauseName
693*0b57cec5SDimitry Andric             << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
694*0b57cec5SDimitry Andric         IsError = true;
695*0b57cec5SDimitry Andric       }
696*0b57cec5SDimitry Andric       BS = Out;
697*0b57cec5SDimitry Andric       BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
698*0b57cec5SDimitry Andric       P.ConsumeToken();
699*0b57cec5SDimitry Andric     } else if (ClauseName.equals("simdlen")) {
700*0b57cec5SDimitry Andric       if (SimdLen.isUsable()) {
701*0b57cec5SDimitry Andric         P.Diag(Tok, diag::err_omp_more_one_clause)
702*0b57cec5SDimitry Andric             << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
703*0b57cec5SDimitry Andric         IsError = true;
704*0b57cec5SDimitry Andric       }
705*0b57cec5SDimitry Andric       P.ConsumeToken();
706*0b57cec5SDimitry Andric       SourceLocation RLoc;
707*0b57cec5SDimitry Andric       SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
708*0b57cec5SDimitry Andric       if (SimdLen.isInvalid())
709*0b57cec5SDimitry Andric         IsError = true;
710*0b57cec5SDimitry Andric     } else {
711*0b57cec5SDimitry Andric       OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
712*0b57cec5SDimitry Andric       if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
713*0b57cec5SDimitry Andric           CKind == OMPC_linear) {
714*0b57cec5SDimitry Andric         Parser::OpenMPVarListDataTy Data;
715*0b57cec5SDimitry Andric         SmallVectorImpl<Expr *> *Vars = &Uniforms;
716*0b57cec5SDimitry Andric         if (CKind == OMPC_aligned)
717*0b57cec5SDimitry Andric           Vars = &Aligneds;
718*0b57cec5SDimitry Andric         else if (CKind == OMPC_linear)
719*0b57cec5SDimitry Andric           Vars = &Linears;
720*0b57cec5SDimitry Andric 
721*0b57cec5SDimitry Andric         P.ConsumeToken();
722*0b57cec5SDimitry Andric         if (P.ParseOpenMPVarList(OMPD_declare_simd,
723*0b57cec5SDimitry Andric                                  getOpenMPClauseKind(ClauseName), *Vars, Data))
724*0b57cec5SDimitry Andric           IsError = true;
725*0b57cec5SDimitry Andric         if (CKind == OMPC_aligned) {
726*0b57cec5SDimitry Andric           Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
727*0b57cec5SDimitry Andric         } else if (CKind == OMPC_linear) {
728*0b57cec5SDimitry Andric           if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
729*0b57cec5SDimitry Andric                                                        Data.DepLinMapLoc))
730*0b57cec5SDimitry Andric             Data.LinKind = OMPC_LINEAR_val;
731*0b57cec5SDimitry Andric           LinModifiers.append(Linears.size() - LinModifiers.size(),
732*0b57cec5SDimitry Andric                               Data.LinKind);
733*0b57cec5SDimitry Andric           Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
734*0b57cec5SDimitry Andric         }
735*0b57cec5SDimitry Andric       } else
736*0b57cec5SDimitry Andric         // TODO: add parsing of other clauses.
737*0b57cec5SDimitry Andric         break;
738*0b57cec5SDimitry Andric     }
739*0b57cec5SDimitry Andric     // Skip ',' if any.
740*0b57cec5SDimitry Andric     if (Tok.is(tok::comma))
741*0b57cec5SDimitry Andric       P.ConsumeToken();
742*0b57cec5SDimitry Andric   }
743*0b57cec5SDimitry Andric   return IsError;
744*0b57cec5SDimitry Andric }
745*0b57cec5SDimitry Andric 
746*0b57cec5SDimitry Andric /// Parse clauses for '#pragma omp declare simd'.
747*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy
748*0b57cec5SDimitry Andric Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
749*0b57cec5SDimitry Andric                                    CachedTokens &Toks, SourceLocation Loc) {
750*0b57cec5SDimitry Andric   PP.EnterToken(Tok, /*IsReinject*/ true);
751*0b57cec5SDimitry Andric   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
752*0b57cec5SDimitry Andric                       /*IsReinject*/ true);
753*0b57cec5SDimitry Andric   // Consume the previously pushed token.
754*0b57cec5SDimitry Andric   ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
755*0b57cec5SDimitry Andric 
756*0b57cec5SDimitry Andric   FNContextRAII FnContext(*this, Ptr);
757*0b57cec5SDimitry Andric   OMPDeclareSimdDeclAttr::BranchStateTy BS =
758*0b57cec5SDimitry Andric       OMPDeclareSimdDeclAttr::BS_Undefined;
759*0b57cec5SDimitry Andric   ExprResult Simdlen;
760*0b57cec5SDimitry Andric   SmallVector<Expr *, 4> Uniforms;
761*0b57cec5SDimitry Andric   SmallVector<Expr *, 4> Aligneds;
762*0b57cec5SDimitry Andric   SmallVector<Expr *, 4> Alignments;
763*0b57cec5SDimitry Andric   SmallVector<Expr *, 4> Linears;
764*0b57cec5SDimitry Andric   SmallVector<unsigned, 4> LinModifiers;
765*0b57cec5SDimitry Andric   SmallVector<Expr *, 4> Steps;
766*0b57cec5SDimitry Andric   bool IsError =
767*0b57cec5SDimitry Andric       parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
768*0b57cec5SDimitry Andric                               Alignments, Linears, LinModifiers, Steps);
769*0b57cec5SDimitry Andric   // Need to check for extra tokens.
770*0b57cec5SDimitry Andric   if (Tok.isNot(tok::annot_pragma_openmp_end)) {
771*0b57cec5SDimitry Andric     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
772*0b57cec5SDimitry Andric         << getOpenMPDirectiveName(OMPD_declare_simd);
773*0b57cec5SDimitry Andric     while (Tok.isNot(tok::annot_pragma_openmp_end))
774*0b57cec5SDimitry Andric       ConsumeAnyToken();
775*0b57cec5SDimitry Andric   }
776*0b57cec5SDimitry Andric   // Skip the last annot_pragma_openmp_end.
777*0b57cec5SDimitry Andric   SourceLocation EndLoc = ConsumeAnnotationToken();
778*0b57cec5SDimitry Andric   if (IsError)
779*0b57cec5SDimitry Andric     return Ptr;
780*0b57cec5SDimitry Andric   return Actions.ActOnOpenMPDeclareSimdDirective(
781*0b57cec5SDimitry Andric       Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
782*0b57cec5SDimitry Andric       LinModifiers, Steps, SourceRange(Loc, EndLoc));
783*0b57cec5SDimitry Andric }
784*0b57cec5SDimitry Andric 
785*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
786*0b57cec5SDimitry Andric   // OpenMP 4.5 syntax with list of entities.
787*0b57cec5SDimitry Andric   Sema::NamedDeclSetType SameDirectiveDecls;
788*0b57cec5SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end)) {
789*0b57cec5SDimitry Andric     OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
790*0b57cec5SDimitry Andric     if (Tok.is(tok::identifier)) {
791*0b57cec5SDimitry Andric       IdentifierInfo *II = Tok.getIdentifierInfo();
792*0b57cec5SDimitry Andric       StringRef ClauseName = II->getName();
793*0b57cec5SDimitry Andric       // Parse 'to|link' clauses.
794*0b57cec5SDimitry Andric       if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) {
795*0b57cec5SDimitry Andric         Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName;
796*0b57cec5SDimitry Andric         break;
797*0b57cec5SDimitry Andric       }
798*0b57cec5SDimitry Andric       ConsumeToken();
799*0b57cec5SDimitry Andric     }
800*0b57cec5SDimitry Andric     auto &&Callback = [this, MT, &SameDirectiveDecls](
801*0b57cec5SDimitry Andric         CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
802*0b57cec5SDimitry Andric       Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
803*0b57cec5SDimitry Andric                                            SameDirectiveDecls);
804*0b57cec5SDimitry Andric     };
805*0b57cec5SDimitry Andric     if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
806*0b57cec5SDimitry Andric                                  /*AllowScopeSpecifier=*/true))
807*0b57cec5SDimitry Andric       break;
808*0b57cec5SDimitry Andric 
809*0b57cec5SDimitry Andric     // Consume optional ','.
810*0b57cec5SDimitry Andric     if (Tok.is(tok::comma))
811*0b57cec5SDimitry Andric       ConsumeToken();
812*0b57cec5SDimitry Andric   }
813*0b57cec5SDimitry Andric   SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
814*0b57cec5SDimitry Andric   ConsumeAnyToken();
815*0b57cec5SDimitry Andric   SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
816*0b57cec5SDimitry Andric                                SameDirectiveDecls.end());
817*0b57cec5SDimitry Andric   if (Decls.empty())
818*0b57cec5SDimitry Andric     return DeclGroupPtrTy();
819*0b57cec5SDimitry Andric   return Actions.BuildDeclaratorGroup(Decls);
820*0b57cec5SDimitry Andric }
821*0b57cec5SDimitry Andric 
822*0b57cec5SDimitry Andric void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
823*0b57cec5SDimitry Andric                                                SourceLocation DTLoc) {
824*0b57cec5SDimitry Andric   if (DKind != OMPD_end_declare_target) {
825*0b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_end_declare_target);
826*0b57cec5SDimitry Andric     Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
827*0b57cec5SDimitry Andric     return;
828*0b57cec5SDimitry Andric   }
829*0b57cec5SDimitry Andric   ConsumeAnyToken();
830*0b57cec5SDimitry Andric   if (Tok.isNot(tok::annot_pragma_openmp_end)) {
831*0b57cec5SDimitry Andric     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
832*0b57cec5SDimitry Andric         << getOpenMPDirectiveName(OMPD_end_declare_target);
833*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
834*0b57cec5SDimitry Andric   }
835*0b57cec5SDimitry Andric   // Skip the last annot_pragma_openmp_end.
836*0b57cec5SDimitry Andric   ConsumeAnyToken();
837*0b57cec5SDimitry Andric }
838*0b57cec5SDimitry Andric 
839*0b57cec5SDimitry Andric /// Parsing of declarative OpenMP directives.
840*0b57cec5SDimitry Andric ///
841*0b57cec5SDimitry Andric ///       threadprivate-directive:
842*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'threadprivate' simple-variable-list
843*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
844*0b57cec5SDimitry Andric ///
845*0b57cec5SDimitry Andric ///       allocate-directive:
846*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
847*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
848*0b57cec5SDimitry Andric ///
849*0b57cec5SDimitry Andric ///       declare-reduction-directive:
850*0b57cec5SDimitry Andric ///        annot_pragma_openmp 'declare' 'reduction' [...]
851*0b57cec5SDimitry Andric ///        annot_pragma_openmp_end
852*0b57cec5SDimitry Andric ///
853*0b57cec5SDimitry Andric ///       declare-mapper-directive:
854*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
855*0b57cec5SDimitry Andric ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
856*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
857*0b57cec5SDimitry Andric ///
858*0b57cec5SDimitry Andric ///       declare-simd-directive:
859*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare simd' {<clause> [,]}
860*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
861*0b57cec5SDimitry Andric ///         <function declaration/definition>
862*0b57cec5SDimitry Andric ///
863*0b57cec5SDimitry Andric ///       requires directive:
864*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
865*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
866*0b57cec5SDimitry Andric ///
867*0b57cec5SDimitry Andric Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
868*0b57cec5SDimitry Andric     AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
869*0b57cec5SDimitry Andric     DeclSpec::TST TagType, Decl *Tag) {
870*0b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
871*0b57cec5SDimitry Andric   ParenBraceBracketBalancer BalancerRAIIObj(*this);
872*0b57cec5SDimitry Andric 
873*0b57cec5SDimitry Andric   SourceLocation Loc = ConsumeAnnotationToken();
874*0b57cec5SDimitry Andric   OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
875*0b57cec5SDimitry Andric 
876*0b57cec5SDimitry Andric   switch (DKind) {
877*0b57cec5SDimitry Andric   case OMPD_threadprivate: {
878*0b57cec5SDimitry Andric     ConsumeToken();
879*0b57cec5SDimitry Andric     DeclDirectiveListParserHelper Helper(this, DKind);
880*0b57cec5SDimitry Andric     if (!ParseOpenMPSimpleVarList(DKind, Helper,
881*0b57cec5SDimitry Andric                                   /*AllowScopeSpecifier=*/true)) {
882*0b57cec5SDimitry Andric       // The last seen token is annot_pragma_openmp_end - need to check for
883*0b57cec5SDimitry Andric       // extra tokens.
884*0b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
885*0b57cec5SDimitry Andric         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
886*0b57cec5SDimitry Andric             << getOpenMPDirectiveName(DKind);
887*0b57cec5SDimitry Andric         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
888*0b57cec5SDimitry Andric       }
889*0b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
890*0b57cec5SDimitry Andric       ConsumeAnnotationToken();
891*0b57cec5SDimitry Andric       return Actions.ActOnOpenMPThreadprivateDirective(Loc,
892*0b57cec5SDimitry Andric                                                        Helper.getIdentifiers());
893*0b57cec5SDimitry Andric     }
894*0b57cec5SDimitry Andric     break;
895*0b57cec5SDimitry Andric   }
896*0b57cec5SDimitry Andric   case OMPD_allocate: {
897*0b57cec5SDimitry Andric     ConsumeToken();
898*0b57cec5SDimitry Andric     DeclDirectiveListParserHelper Helper(this, DKind);
899*0b57cec5SDimitry Andric     if (!ParseOpenMPSimpleVarList(DKind, Helper,
900*0b57cec5SDimitry Andric                                   /*AllowScopeSpecifier=*/true)) {
901*0b57cec5SDimitry Andric       SmallVector<OMPClause *, 1> Clauses;
902*0b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
903*0b57cec5SDimitry Andric         SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
904*0b57cec5SDimitry Andric                     OMPC_unknown + 1>
905*0b57cec5SDimitry Andric             FirstClauses(OMPC_unknown + 1);
906*0b57cec5SDimitry Andric         while (Tok.isNot(tok::annot_pragma_openmp_end)) {
907*0b57cec5SDimitry Andric           OpenMPClauseKind CKind =
908*0b57cec5SDimitry Andric               Tok.isAnnotation() ? OMPC_unknown
909*0b57cec5SDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
910*0b57cec5SDimitry Andric           Actions.StartOpenMPClause(CKind);
911*0b57cec5SDimitry Andric           OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
912*0b57cec5SDimitry Andric                                                 !FirstClauses[CKind].getInt());
913*0b57cec5SDimitry Andric           SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
914*0b57cec5SDimitry Andric                     StopBeforeMatch);
915*0b57cec5SDimitry Andric           FirstClauses[CKind].setInt(true);
916*0b57cec5SDimitry Andric           if (Clause != nullptr)
917*0b57cec5SDimitry Andric             Clauses.push_back(Clause);
918*0b57cec5SDimitry Andric           if (Tok.is(tok::annot_pragma_openmp_end)) {
919*0b57cec5SDimitry Andric             Actions.EndOpenMPClause();
920*0b57cec5SDimitry Andric             break;
921*0b57cec5SDimitry Andric           }
922*0b57cec5SDimitry Andric           // Skip ',' if any.
923*0b57cec5SDimitry Andric           if (Tok.is(tok::comma))
924*0b57cec5SDimitry Andric             ConsumeToken();
925*0b57cec5SDimitry Andric           Actions.EndOpenMPClause();
926*0b57cec5SDimitry Andric         }
927*0b57cec5SDimitry Andric         // The last seen token is annot_pragma_openmp_end - need to check for
928*0b57cec5SDimitry Andric         // extra tokens.
929*0b57cec5SDimitry Andric         if (Tok.isNot(tok::annot_pragma_openmp_end)) {
930*0b57cec5SDimitry Andric           Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
931*0b57cec5SDimitry Andric               << getOpenMPDirectiveName(DKind);
932*0b57cec5SDimitry Andric           SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
933*0b57cec5SDimitry Andric         }
934*0b57cec5SDimitry Andric       }
935*0b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
936*0b57cec5SDimitry Andric       ConsumeAnnotationToken();
937*0b57cec5SDimitry Andric       return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
938*0b57cec5SDimitry Andric                                                   Clauses);
939*0b57cec5SDimitry Andric     }
940*0b57cec5SDimitry Andric     break;
941*0b57cec5SDimitry Andric   }
942*0b57cec5SDimitry Andric   case OMPD_requires: {
943*0b57cec5SDimitry Andric     SourceLocation StartLoc = ConsumeToken();
944*0b57cec5SDimitry Andric     SmallVector<OMPClause *, 5> Clauses;
945*0b57cec5SDimitry Andric     SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
946*0b57cec5SDimitry Andric     FirstClauses(OMPC_unknown + 1);
947*0b57cec5SDimitry Andric     if (Tok.is(tok::annot_pragma_openmp_end)) {
948*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_expected_clause)
949*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(OMPD_requires);
950*0b57cec5SDimitry Andric       break;
951*0b57cec5SDimitry Andric     }
952*0b57cec5SDimitry Andric     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
953*0b57cec5SDimitry Andric       OpenMPClauseKind CKind = Tok.isAnnotation()
954*0b57cec5SDimitry Andric                                    ? OMPC_unknown
955*0b57cec5SDimitry Andric                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
956*0b57cec5SDimitry Andric       Actions.StartOpenMPClause(CKind);
957*0b57cec5SDimitry Andric       OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
958*0b57cec5SDimitry Andric                                             !FirstClauses[CKind].getInt());
959*0b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
960*0b57cec5SDimitry Andric                 StopBeforeMatch);
961*0b57cec5SDimitry Andric       FirstClauses[CKind].setInt(true);
962*0b57cec5SDimitry Andric       if (Clause != nullptr)
963*0b57cec5SDimitry Andric         Clauses.push_back(Clause);
964*0b57cec5SDimitry Andric       if (Tok.is(tok::annot_pragma_openmp_end)) {
965*0b57cec5SDimitry Andric         Actions.EndOpenMPClause();
966*0b57cec5SDimitry Andric         break;
967*0b57cec5SDimitry Andric       }
968*0b57cec5SDimitry Andric       // Skip ',' if any.
969*0b57cec5SDimitry Andric       if (Tok.is(tok::comma))
970*0b57cec5SDimitry Andric         ConsumeToken();
971*0b57cec5SDimitry Andric       Actions.EndOpenMPClause();
972*0b57cec5SDimitry Andric     }
973*0b57cec5SDimitry Andric     // Consume final annot_pragma_openmp_end
974*0b57cec5SDimitry Andric     if (Clauses.size() == 0) {
975*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_expected_clause)
976*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(OMPD_requires);
977*0b57cec5SDimitry Andric       ConsumeAnnotationToken();
978*0b57cec5SDimitry Andric       return nullptr;
979*0b57cec5SDimitry Andric     }
980*0b57cec5SDimitry Andric     ConsumeAnnotationToken();
981*0b57cec5SDimitry Andric     return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
982*0b57cec5SDimitry Andric   }
983*0b57cec5SDimitry Andric   case OMPD_declare_reduction:
984*0b57cec5SDimitry Andric     ConsumeToken();
985*0b57cec5SDimitry Andric     if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
986*0b57cec5SDimitry Andric       // The last seen token is annot_pragma_openmp_end - need to check for
987*0b57cec5SDimitry Andric       // extra tokens.
988*0b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
989*0b57cec5SDimitry Andric         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
990*0b57cec5SDimitry Andric             << getOpenMPDirectiveName(OMPD_declare_reduction);
991*0b57cec5SDimitry Andric         while (Tok.isNot(tok::annot_pragma_openmp_end))
992*0b57cec5SDimitry Andric           ConsumeAnyToken();
993*0b57cec5SDimitry Andric       }
994*0b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
995*0b57cec5SDimitry Andric       ConsumeAnnotationToken();
996*0b57cec5SDimitry Andric       return Res;
997*0b57cec5SDimitry Andric     }
998*0b57cec5SDimitry Andric     break;
999*0b57cec5SDimitry Andric   case OMPD_declare_mapper: {
1000*0b57cec5SDimitry Andric     ConsumeToken();
1001*0b57cec5SDimitry Andric     if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
1002*0b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
1003*0b57cec5SDimitry Andric       ConsumeAnnotationToken();
1004*0b57cec5SDimitry Andric       return Res;
1005*0b57cec5SDimitry Andric     }
1006*0b57cec5SDimitry Andric     break;
1007*0b57cec5SDimitry Andric   }
1008*0b57cec5SDimitry Andric   case OMPD_declare_simd: {
1009*0b57cec5SDimitry Andric     // The syntax is:
1010*0b57cec5SDimitry Andric     // { #pragma omp declare simd }
1011*0b57cec5SDimitry Andric     // <function-declaration-or-definition>
1012*0b57cec5SDimitry Andric     //
1013*0b57cec5SDimitry Andric     ConsumeToken();
1014*0b57cec5SDimitry Andric     CachedTokens Toks;
1015*0b57cec5SDimitry Andric     while(Tok.isNot(tok::annot_pragma_openmp_end)) {
1016*0b57cec5SDimitry Andric       Toks.push_back(Tok);
1017*0b57cec5SDimitry Andric       ConsumeAnyToken();
1018*0b57cec5SDimitry Andric     }
1019*0b57cec5SDimitry Andric     Toks.push_back(Tok);
1020*0b57cec5SDimitry Andric     ConsumeAnyToken();
1021*0b57cec5SDimitry Andric 
1022*0b57cec5SDimitry Andric     DeclGroupPtrTy Ptr;
1023*0b57cec5SDimitry Andric     if (Tok.is(tok::annot_pragma_openmp)) {
1024*0b57cec5SDimitry Andric       Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
1025*0b57cec5SDimitry Andric     } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1026*0b57cec5SDimitry Andric       // Here we expect to see some function declaration.
1027*0b57cec5SDimitry Andric       if (AS == AS_none) {
1028*0b57cec5SDimitry Andric         assert(TagType == DeclSpec::TST_unspecified);
1029*0b57cec5SDimitry Andric         MaybeParseCXX11Attributes(Attrs);
1030*0b57cec5SDimitry Andric         ParsingDeclSpec PDS(*this);
1031*0b57cec5SDimitry Andric         Ptr = ParseExternalDeclaration(Attrs, &PDS);
1032*0b57cec5SDimitry Andric       } else {
1033*0b57cec5SDimitry Andric         Ptr =
1034*0b57cec5SDimitry Andric             ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1035*0b57cec5SDimitry Andric       }
1036*0b57cec5SDimitry Andric     }
1037*0b57cec5SDimitry Andric     if (!Ptr) {
1038*0b57cec5SDimitry Andric       Diag(Loc, diag::err_omp_decl_in_declare_simd);
1039*0b57cec5SDimitry Andric       return DeclGroupPtrTy();
1040*0b57cec5SDimitry Andric     }
1041*0b57cec5SDimitry Andric     return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
1042*0b57cec5SDimitry Andric   }
1043*0b57cec5SDimitry Andric   case OMPD_declare_target: {
1044*0b57cec5SDimitry Andric     SourceLocation DTLoc = ConsumeAnyToken();
1045*0b57cec5SDimitry Andric     if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1046*0b57cec5SDimitry Andric       return ParseOMPDeclareTargetClauses();
1047*0b57cec5SDimitry Andric     }
1048*0b57cec5SDimitry Andric 
1049*0b57cec5SDimitry Andric     // Skip the last annot_pragma_openmp_end.
1050*0b57cec5SDimitry Andric     ConsumeAnyToken();
1051*0b57cec5SDimitry Andric 
1052*0b57cec5SDimitry Andric     if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1053*0b57cec5SDimitry Andric       return DeclGroupPtrTy();
1054*0b57cec5SDimitry Andric 
1055*0b57cec5SDimitry Andric     llvm::SmallVector<Decl *, 4>  Decls;
1056*0b57cec5SDimitry Andric     DKind = parseOpenMPDirectiveKind(*this);
1057*0b57cec5SDimitry Andric     while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
1058*0b57cec5SDimitry Andric            Tok.isNot(tok::r_brace)) {
1059*0b57cec5SDimitry Andric       DeclGroupPtrTy Ptr;
1060*0b57cec5SDimitry Andric       // Here we expect to see some function declaration.
1061*0b57cec5SDimitry Andric       if (AS == AS_none) {
1062*0b57cec5SDimitry Andric         assert(TagType == DeclSpec::TST_unspecified);
1063*0b57cec5SDimitry Andric         MaybeParseCXX11Attributes(Attrs);
1064*0b57cec5SDimitry Andric         ParsingDeclSpec PDS(*this);
1065*0b57cec5SDimitry Andric         Ptr = ParseExternalDeclaration(Attrs, &PDS);
1066*0b57cec5SDimitry Andric       } else {
1067*0b57cec5SDimitry Andric         Ptr =
1068*0b57cec5SDimitry Andric             ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
1069*0b57cec5SDimitry Andric       }
1070*0b57cec5SDimitry Andric       if (Ptr) {
1071*0b57cec5SDimitry Andric         DeclGroupRef Ref = Ptr.get();
1072*0b57cec5SDimitry Andric         Decls.append(Ref.begin(), Ref.end());
1073*0b57cec5SDimitry Andric       }
1074*0b57cec5SDimitry Andric       if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
1075*0b57cec5SDimitry Andric         TentativeParsingAction TPA(*this);
1076*0b57cec5SDimitry Andric         ConsumeAnnotationToken();
1077*0b57cec5SDimitry Andric         DKind = parseOpenMPDirectiveKind(*this);
1078*0b57cec5SDimitry Andric         if (DKind != OMPD_end_declare_target)
1079*0b57cec5SDimitry Andric           TPA.Revert();
1080*0b57cec5SDimitry Andric         else
1081*0b57cec5SDimitry Andric           TPA.Commit();
1082*0b57cec5SDimitry Andric       }
1083*0b57cec5SDimitry Andric     }
1084*0b57cec5SDimitry Andric 
1085*0b57cec5SDimitry Andric     ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
1086*0b57cec5SDimitry Andric     Actions.ActOnFinishOpenMPDeclareTargetDirective();
1087*0b57cec5SDimitry Andric     return Actions.BuildDeclaratorGroup(Decls);
1088*0b57cec5SDimitry Andric   }
1089*0b57cec5SDimitry Andric   case OMPD_unknown:
1090*0b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_unknown_directive);
1091*0b57cec5SDimitry Andric     break;
1092*0b57cec5SDimitry Andric   case OMPD_parallel:
1093*0b57cec5SDimitry Andric   case OMPD_simd:
1094*0b57cec5SDimitry Andric   case OMPD_task:
1095*0b57cec5SDimitry Andric   case OMPD_taskyield:
1096*0b57cec5SDimitry Andric   case OMPD_barrier:
1097*0b57cec5SDimitry Andric   case OMPD_taskwait:
1098*0b57cec5SDimitry Andric   case OMPD_taskgroup:
1099*0b57cec5SDimitry Andric   case OMPD_flush:
1100*0b57cec5SDimitry Andric   case OMPD_for:
1101*0b57cec5SDimitry Andric   case OMPD_for_simd:
1102*0b57cec5SDimitry Andric   case OMPD_sections:
1103*0b57cec5SDimitry Andric   case OMPD_section:
1104*0b57cec5SDimitry Andric   case OMPD_single:
1105*0b57cec5SDimitry Andric   case OMPD_master:
1106*0b57cec5SDimitry Andric   case OMPD_ordered:
1107*0b57cec5SDimitry Andric   case OMPD_critical:
1108*0b57cec5SDimitry Andric   case OMPD_parallel_for:
1109*0b57cec5SDimitry Andric   case OMPD_parallel_for_simd:
1110*0b57cec5SDimitry Andric   case OMPD_parallel_sections:
1111*0b57cec5SDimitry Andric   case OMPD_atomic:
1112*0b57cec5SDimitry Andric   case OMPD_target:
1113*0b57cec5SDimitry Andric   case OMPD_teams:
1114*0b57cec5SDimitry Andric   case OMPD_cancellation_point:
1115*0b57cec5SDimitry Andric   case OMPD_cancel:
1116*0b57cec5SDimitry Andric   case OMPD_target_data:
1117*0b57cec5SDimitry Andric   case OMPD_target_enter_data:
1118*0b57cec5SDimitry Andric   case OMPD_target_exit_data:
1119*0b57cec5SDimitry Andric   case OMPD_target_parallel:
1120*0b57cec5SDimitry Andric   case OMPD_target_parallel_for:
1121*0b57cec5SDimitry Andric   case OMPD_taskloop:
1122*0b57cec5SDimitry Andric   case OMPD_taskloop_simd:
1123*0b57cec5SDimitry Andric   case OMPD_distribute:
1124*0b57cec5SDimitry Andric   case OMPD_end_declare_target:
1125*0b57cec5SDimitry Andric   case OMPD_target_update:
1126*0b57cec5SDimitry Andric   case OMPD_distribute_parallel_for:
1127*0b57cec5SDimitry Andric   case OMPD_distribute_parallel_for_simd:
1128*0b57cec5SDimitry Andric   case OMPD_distribute_simd:
1129*0b57cec5SDimitry Andric   case OMPD_target_parallel_for_simd:
1130*0b57cec5SDimitry Andric   case OMPD_target_simd:
1131*0b57cec5SDimitry Andric   case OMPD_teams_distribute:
1132*0b57cec5SDimitry Andric   case OMPD_teams_distribute_simd:
1133*0b57cec5SDimitry Andric   case OMPD_teams_distribute_parallel_for_simd:
1134*0b57cec5SDimitry Andric   case OMPD_teams_distribute_parallel_for:
1135*0b57cec5SDimitry Andric   case OMPD_target_teams:
1136*0b57cec5SDimitry Andric   case OMPD_target_teams_distribute:
1137*0b57cec5SDimitry Andric   case OMPD_target_teams_distribute_parallel_for:
1138*0b57cec5SDimitry Andric   case OMPD_target_teams_distribute_parallel_for_simd:
1139*0b57cec5SDimitry Andric   case OMPD_target_teams_distribute_simd:
1140*0b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_unexpected_directive)
1141*0b57cec5SDimitry Andric         << 1 << getOpenMPDirectiveName(DKind);
1142*0b57cec5SDimitry Andric     break;
1143*0b57cec5SDimitry Andric   }
1144*0b57cec5SDimitry Andric   while (Tok.isNot(tok::annot_pragma_openmp_end))
1145*0b57cec5SDimitry Andric     ConsumeAnyToken();
1146*0b57cec5SDimitry Andric   ConsumeAnyToken();
1147*0b57cec5SDimitry Andric   return nullptr;
1148*0b57cec5SDimitry Andric }
1149*0b57cec5SDimitry Andric 
1150*0b57cec5SDimitry Andric /// Parsing of declarative or executable OpenMP directives.
1151*0b57cec5SDimitry Andric ///
1152*0b57cec5SDimitry Andric ///       threadprivate-directive:
1153*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'threadprivate' simple-variable-list
1154*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
1155*0b57cec5SDimitry Andric ///
1156*0b57cec5SDimitry Andric ///       allocate-directive:
1157*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'allocate' simple-variable-list
1158*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
1159*0b57cec5SDimitry Andric ///
1160*0b57cec5SDimitry Andric ///       declare-reduction-directive:
1161*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
1162*0b57cec5SDimitry Andric ///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
1163*0b57cec5SDimitry Andric ///         ('omp_priv' '=' <expression>|<function_call>) ')']
1164*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
1165*0b57cec5SDimitry Andric ///
1166*0b57cec5SDimitry Andric ///       declare-mapper-directive:
1167*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
1168*0b57cec5SDimitry Andric ///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
1169*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
1170*0b57cec5SDimitry Andric ///
1171*0b57cec5SDimitry Andric ///       executable-directive:
1172*0b57cec5SDimitry Andric ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
1173*0b57cec5SDimitry Andric ///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
1174*0b57cec5SDimitry Andric ///         'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
1175*0b57cec5SDimitry Andric ///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
1176*0b57cec5SDimitry Andric ///         'for simd' | 'parallel for simd' | 'target' | 'target data' |
1177*0b57cec5SDimitry Andric ///         'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
1178*0b57cec5SDimitry Andric ///         'distribute' | 'target enter data' | 'target exit data' |
1179*0b57cec5SDimitry Andric ///         'target parallel' | 'target parallel for' |
1180*0b57cec5SDimitry Andric ///         'target update' | 'distribute parallel for' |
1181*0b57cec5SDimitry Andric ///         'distribute paralle for simd' | 'distribute simd' |
1182*0b57cec5SDimitry Andric ///         'target parallel for simd' | 'target simd' |
1183*0b57cec5SDimitry Andric ///         'teams distribute' | 'teams distribute simd' |
1184*0b57cec5SDimitry Andric ///         'teams distribute parallel for simd' |
1185*0b57cec5SDimitry Andric ///         'teams distribute parallel for' | 'target teams' |
1186*0b57cec5SDimitry Andric ///         'target teams distribute' |
1187*0b57cec5SDimitry Andric ///         'target teams distribute parallel for' |
1188*0b57cec5SDimitry Andric ///         'target teams distribute parallel for simd' |
1189*0b57cec5SDimitry Andric ///         'target teams distribute simd' {clause}
1190*0b57cec5SDimitry Andric ///         annot_pragma_openmp_end
1191*0b57cec5SDimitry Andric ///
1192*0b57cec5SDimitry Andric StmtResult
1193*0b57cec5SDimitry Andric Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
1194*0b57cec5SDimitry Andric   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
1195*0b57cec5SDimitry Andric   ParenBraceBracketBalancer BalancerRAIIObj(*this);
1196*0b57cec5SDimitry Andric   SmallVector<OMPClause *, 5> Clauses;
1197*0b57cec5SDimitry Andric   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
1198*0b57cec5SDimitry Andric   FirstClauses(OMPC_unknown + 1);
1199*0b57cec5SDimitry Andric   unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
1200*0b57cec5SDimitry Andric                         Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
1201*0b57cec5SDimitry Andric   SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
1202*0b57cec5SDimitry Andric   OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
1203*0b57cec5SDimitry Andric   OpenMPDirectiveKind CancelRegion = OMPD_unknown;
1204*0b57cec5SDimitry Andric   // Name of critical directive.
1205*0b57cec5SDimitry Andric   DeclarationNameInfo DirName;
1206*0b57cec5SDimitry Andric   StmtResult Directive = StmtError();
1207*0b57cec5SDimitry Andric   bool HasAssociatedStatement = true;
1208*0b57cec5SDimitry Andric   bool FlushHasClause = false;
1209*0b57cec5SDimitry Andric 
1210*0b57cec5SDimitry Andric   switch (DKind) {
1211*0b57cec5SDimitry Andric   case OMPD_threadprivate: {
1212*0b57cec5SDimitry Andric     // FIXME: Should this be permitted in C++?
1213*0b57cec5SDimitry Andric     if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1214*0b57cec5SDimitry Andric         ParsedStmtContext()) {
1215*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_immediate_directive)
1216*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << 0;
1217*0b57cec5SDimitry Andric     }
1218*0b57cec5SDimitry Andric     ConsumeToken();
1219*0b57cec5SDimitry Andric     DeclDirectiveListParserHelper Helper(this, DKind);
1220*0b57cec5SDimitry Andric     if (!ParseOpenMPSimpleVarList(DKind, Helper,
1221*0b57cec5SDimitry Andric                                   /*AllowScopeSpecifier=*/false)) {
1222*0b57cec5SDimitry Andric       // The last seen token is annot_pragma_openmp_end - need to check for
1223*0b57cec5SDimitry Andric       // extra tokens.
1224*0b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1225*0b57cec5SDimitry Andric         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1226*0b57cec5SDimitry Andric             << getOpenMPDirectiveName(DKind);
1227*0b57cec5SDimitry Andric         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1228*0b57cec5SDimitry Andric       }
1229*0b57cec5SDimitry Andric       DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
1230*0b57cec5SDimitry Andric           Loc, Helper.getIdentifiers());
1231*0b57cec5SDimitry Andric       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1232*0b57cec5SDimitry Andric     }
1233*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end);
1234*0b57cec5SDimitry Andric     break;
1235*0b57cec5SDimitry Andric   }
1236*0b57cec5SDimitry Andric   case OMPD_allocate: {
1237*0b57cec5SDimitry Andric     // FIXME: Should this be permitted in C++?
1238*0b57cec5SDimitry Andric     if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1239*0b57cec5SDimitry Andric         ParsedStmtContext()) {
1240*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_immediate_directive)
1241*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << 0;
1242*0b57cec5SDimitry Andric     }
1243*0b57cec5SDimitry Andric     ConsumeToken();
1244*0b57cec5SDimitry Andric     DeclDirectiveListParserHelper Helper(this, DKind);
1245*0b57cec5SDimitry Andric     if (!ParseOpenMPSimpleVarList(DKind, Helper,
1246*0b57cec5SDimitry Andric                                   /*AllowScopeSpecifier=*/false)) {
1247*0b57cec5SDimitry Andric       SmallVector<OMPClause *, 1> Clauses;
1248*0b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1249*0b57cec5SDimitry Andric         SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
1250*0b57cec5SDimitry Andric                     OMPC_unknown + 1>
1251*0b57cec5SDimitry Andric             FirstClauses(OMPC_unknown + 1);
1252*0b57cec5SDimitry Andric         while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1253*0b57cec5SDimitry Andric           OpenMPClauseKind CKind =
1254*0b57cec5SDimitry Andric               Tok.isAnnotation() ? OMPC_unknown
1255*0b57cec5SDimitry Andric                                  : getOpenMPClauseKind(PP.getSpelling(Tok));
1256*0b57cec5SDimitry Andric           Actions.StartOpenMPClause(CKind);
1257*0b57cec5SDimitry Andric           OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1258*0b57cec5SDimitry Andric                                                 !FirstClauses[CKind].getInt());
1259*0b57cec5SDimitry Andric           SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1260*0b57cec5SDimitry Andric                     StopBeforeMatch);
1261*0b57cec5SDimitry Andric           FirstClauses[CKind].setInt(true);
1262*0b57cec5SDimitry Andric           if (Clause != nullptr)
1263*0b57cec5SDimitry Andric             Clauses.push_back(Clause);
1264*0b57cec5SDimitry Andric           if (Tok.is(tok::annot_pragma_openmp_end)) {
1265*0b57cec5SDimitry Andric             Actions.EndOpenMPClause();
1266*0b57cec5SDimitry Andric             break;
1267*0b57cec5SDimitry Andric           }
1268*0b57cec5SDimitry Andric           // Skip ',' if any.
1269*0b57cec5SDimitry Andric           if (Tok.is(tok::comma))
1270*0b57cec5SDimitry Andric             ConsumeToken();
1271*0b57cec5SDimitry Andric           Actions.EndOpenMPClause();
1272*0b57cec5SDimitry Andric         }
1273*0b57cec5SDimitry Andric         // The last seen token is annot_pragma_openmp_end - need to check for
1274*0b57cec5SDimitry Andric         // extra tokens.
1275*0b57cec5SDimitry Andric         if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1276*0b57cec5SDimitry Andric           Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1277*0b57cec5SDimitry Andric               << getOpenMPDirectiveName(DKind);
1278*0b57cec5SDimitry Andric           SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1279*0b57cec5SDimitry Andric         }
1280*0b57cec5SDimitry Andric       }
1281*0b57cec5SDimitry Andric       DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
1282*0b57cec5SDimitry Andric           Loc, Helper.getIdentifiers(), Clauses);
1283*0b57cec5SDimitry Andric       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1284*0b57cec5SDimitry Andric     }
1285*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end);
1286*0b57cec5SDimitry Andric     break;
1287*0b57cec5SDimitry Andric   }
1288*0b57cec5SDimitry Andric   case OMPD_declare_reduction:
1289*0b57cec5SDimitry Andric     ConsumeToken();
1290*0b57cec5SDimitry Andric     if (DeclGroupPtrTy Res =
1291*0b57cec5SDimitry Andric             ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
1292*0b57cec5SDimitry Andric       // The last seen token is annot_pragma_openmp_end - need to check for
1293*0b57cec5SDimitry Andric       // extra tokens.
1294*0b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
1295*0b57cec5SDimitry Andric         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1296*0b57cec5SDimitry Andric             << getOpenMPDirectiveName(OMPD_declare_reduction);
1297*0b57cec5SDimitry Andric         while (Tok.isNot(tok::annot_pragma_openmp_end))
1298*0b57cec5SDimitry Andric           ConsumeAnyToken();
1299*0b57cec5SDimitry Andric       }
1300*0b57cec5SDimitry Andric       ConsumeAnyToken();
1301*0b57cec5SDimitry Andric       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1302*0b57cec5SDimitry Andric     } else {
1303*0b57cec5SDimitry Andric       SkipUntil(tok::annot_pragma_openmp_end);
1304*0b57cec5SDimitry Andric     }
1305*0b57cec5SDimitry Andric     break;
1306*0b57cec5SDimitry Andric   case OMPD_declare_mapper: {
1307*0b57cec5SDimitry Andric     ConsumeToken();
1308*0b57cec5SDimitry Andric     if (DeclGroupPtrTy Res =
1309*0b57cec5SDimitry Andric             ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
1310*0b57cec5SDimitry Andric       // Skip the last annot_pragma_openmp_end.
1311*0b57cec5SDimitry Andric       ConsumeAnnotationToken();
1312*0b57cec5SDimitry Andric       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
1313*0b57cec5SDimitry Andric     } else {
1314*0b57cec5SDimitry Andric       SkipUntil(tok::annot_pragma_openmp_end);
1315*0b57cec5SDimitry Andric     }
1316*0b57cec5SDimitry Andric     break;
1317*0b57cec5SDimitry Andric   }
1318*0b57cec5SDimitry Andric   case OMPD_flush:
1319*0b57cec5SDimitry Andric     if (PP.LookAhead(0).is(tok::l_paren)) {
1320*0b57cec5SDimitry Andric       FlushHasClause = true;
1321*0b57cec5SDimitry Andric       // Push copy of the current token back to stream to properly parse
1322*0b57cec5SDimitry Andric       // pseudo-clause OMPFlushClause.
1323*0b57cec5SDimitry Andric       PP.EnterToken(Tok, /*IsReinject*/ true);
1324*0b57cec5SDimitry Andric     }
1325*0b57cec5SDimitry Andric     LLVM_FALLTHROUGH;
1326*0b57cec5SDimitry Andric   case OMPD_taskyield:
1327*0b57cec5SDimitry Andric   case OMPD_barrier:
1328*0b57cec5SDimitry Andric   case OMPD_taskwait:
1329*0b57cec5SDimitry Andric   case OMPD_cancellation_point:
1330*0b57cec5SDimitry Andric   case OMPD_cancel:
1331*0b57cec5SDimitry Andric   case OMPD_target_enter_data:
1332*0b57cec5SDimitry Andric   case OMPD_target_exit_data:
1333*0b57cec5SDimitry Andric   case OMPD_target_update:
1334*0b57cec5SDimitry Andric     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1335*0b57cec5SDimitry Andric         ParsedStmtContext()) {
1336*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_immediate_directive)
1337*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << 0;
1338*0b57cec5SDimitry Andric     }
1339*0b57cec5SDimitry Andric     HasAssociatedStatement = false;
1340*0b57cec5SDimitry Andric     // Fall through for further analysis.
1341*0b57cec5SDimitry Andric     LLVM_FALLTHROUGH;
1342*0b57cec5SDimitry Andric   case OMPD_parallel:
1343*0b57cec5SDimitry Andric   case OMPD_simd:
1344*0b57cec5SDimitry Andric   case OMPD_for:
1345*0b57cec5SDimitry Andric   case OMPD_for_simd:
1346*0b57cec5SDimitry Andric   case OMPD_sections:
1347*0b57cec5SDimitry Andric   case OMPD_single:
1348*0b57cec5SDimitry Andric   case OMPD_section:
1349*0b57cec5SDimitry Andric   case OMPD_master:
1350*0b57cec5SDimitry Andric   case OMPD_critical:
1351*0b57cec5SDimitry Andric   case OMPD_parallel_for:
1352*0b57cec5SDimitry Andric   case OMPD_parallel_for_simd:
1353*0b57cec5SDimitry Andric   case OMPD_parallel_sections:
1354*0b57cec5SDimitry Andric   case OMPD_task:
1355*0b57cec5SDimitry Andric   case OMPD_ordered:
1356*0b57cec5SDimitry Andric   case OMPD_atomic:
1357*0b57cec5SDimitry Andric   case OMPD_target:
1358*0b57cec5SDimitry Andric   case OMPD_teams:
1359*0b57cec5SDimitry Andric   case OMPD_taskgroup:
1360*0b57cec5SDimitry Andric   case OMPD_target_data:
1361*0b57cec5SDimitry Andric   case OMPD_target_parallel:
1362*0b57cec5SDimitry Andric   case OMPD_target_parallel_for:
1363*0b57cec5SDimitry Andric   case OMPD_taskloop:
1364*0b57cec5SDimitry Andric   case OMPD_taskloop_simd:
1365*0b57cec5SDimitry Andric   case OMPD_distribute:
1366*0b57cec5SDimitry Andric   case OMPD_distribute_parallel_for:
1367*0b57cec5SDimitry Andric   case OMPD_distribute_parallel_for_simd:
1368*0b57cec5SDimitry Andric   case OMPD_distribute_simd:
1369*0b57cec5SDimitry Andric   case OMPD_target_parallel_for_simd:
1370*0b57cec5SDimitry Andric   case OMPD_target_simd:
1371*0b57cec5SDimitry Andric   case OMPD_teams_distribute:
1372*0b57cec5SDimitry Andric   case OMPD_teams_distribute_simd:
1373*0b57cec5SDimitry Andric   case OMPD_teams_distribute_parallel_for_simd:
1374*0b57cec5SDimitry Andric   case OMPD_teams_distribute_parallel_for:
1375*0b57cec5SDimitry Andric   case OMPD_target_teams:
1376*0b57cec5SDimitry Andric   case OMPD_target_teams_distribute:
1377*0b57cec5SDimitry Andric   case OMPD_target_teams_distribute_parallel_for:
1378*0b57cec5SDimitry Andric   case OMPD_target_teams_distribute_parallel_for_simd:
1379*0b57cec5SDimitry Andric   case OMPD_target_teams_distribute_simd: {
1380*0b57cec5SDimitry Andric     ConsumeToken();
1381*0b57cec5SDimitry Andric     // Parse directive name of the 'critical' directive if any.
1382*0b57cec5SDimitry Andric     if (DKind == OMPD_critical) {
1383*0b57cec5SDimitry Andric       BalancedDelimiterTracker T(*this, tok::l_paren,
1384*0b57cec5SDimitry Andric                                  tok::annot_pragma_openmp_end);
1385*0b57cec5SDimitry Andric       if (!T.consumeOpen()) {
1386*0b57cec5SDimitry Andric         if (Tok.isAnyIdentifier()) {
1387*0b57cec5SDimitry Andric           DirName =
1388*0b57cec5SDimitry Andric               DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
1389*0b57cec5SDimitry Andric           ConsumeAnyToken();
1390*0b57cec5SDimitry Andric         } else {
1391*0b57cec5SDimitry Andric           Diag(Tok, diag::err_omp_expected_identifier_for_critical);
1392*0b57cec5SDimitry Andric         }
1393*0b57cec5SDimitry Andric         T.consumeClose();
1394*0b57cec5SDimitry Andric       }
1395*0b57cec5SDimitry Andric     } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1396*0b57cec5SDimitry Andric       CancelRegion = parseOpenMPDirectiveKind(*this);
1397*0b57cec5SDimitry Andric       if (Tok.isNot(tok::annot_pragma_openmp_end))
1398*0b57cec5SDimitry Andric         ConsumeToken();
1399*0b57cec5SDimitry Andric     }
1400*0b57cec5SDimitry Andric 
1401*0b57cec5SDimitry Andric     if (isOpenMPLoopDirective(DKind))
1402*0b57cec5SDimitry Andric       ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
1403*0b57cec5SDimitry Andric     if (isOpenMPSimdDirective(DKind))
1404*0b57cec5SDimitry Andric       ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
1405*0b57cec5SDimitry Andric     ParseScope OMPDirectiveScope(this, ScopeFlags);
1406*0b57cec5SDimitry Andric     Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1407*0b57cec5SDimitry Andric 
1408*0b57cec5SDimitry Andric     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1409*0b57cec5SDimitry Andric       OpenMPClauseKind CKind =
1410*0b57cec5SDimitry Andric           Tok.isAnnotation()
1411*0b57cec5SDimitry Andric               ? OMPC_unknown
1412*0b57cec5SDimitry Andric               : FlushHasClause ? OMPC_flush
1413*0b57cec5SDimitry Andric                                : getOpenMPClauseKind(PP.getSpelling(Tok));
1414*0b57cec5SDimitry Andric       Actions.StartOpenMPClause(CKind);
1415*0b57cec5SDimitry Andric       FlushHasClause = false;
1416*0b57cec5SDimitry Andric       OMPClause *Clause =
1417*0b57cec5SDimitry Andric           ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1418*0b57cec5SDimitry Andric       FirstClauses[CKind].setInt(true);
1419*0b57cec5SDimitry Andric       if (Clause) {
1420*0b57cec5SDimitry Andric         FirstClauses[CKind].setPointer(Clause);
1421*0b57cec5SDimitry Andric         Clauses.push_back(Clause);
1422*0b57cec5SDimitry Andric       }
1423*0b57cec5SDimitry Andric 
1424*0b57cec5SDimitry Andric       // Skip ',' if any.
1425*0b57cec5SDimitry Andric       if (Tok.is(tok::comma))
1426*0b57cec5SDimitry Andric         ConsumeToken();
1427*0b57cec5SDimitry Andric       Actions.EndOpenMPClause();
1428*0b57cec5SDimitry Andric     }
1429*0b57cec5SDimitry Andric     // End location of the directive.
1430*0b57cec5SDimitry Andric     EndLoc = Tok.getLocation();
1431*0b57cec5SDimitry Andric     // Consume final annot_pragma_openmp_end.
1432*0b57cec5SDimitry Andric     ConsumeAnnotationToken();
1433*0b57cec5SDimitry Andric 
1434*0b57cec5SDimitry Andric     // OpenMP [2.13.8, ordered Construct, Syntax]
1435*0b57cec5SDimitry Andric     // If the depend clause is specified, the ordered construct is a stand-alone
1436*0b57cec5SDimitry Andric     // directive.
1437*0b57cec5SDimitry Andric     if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1438*0b57cec5SDimitry Andric       if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1439*0b57cec5SDimitry Andric           ParsedStmtContext()) {
1440*0b57cec5SDimitry Andric         Diag(Loc, diag::err_omp_immediate_directive)
1441*0b57cec5SDimitry Andric             << getOpenMPDirectiveName(DKind) << 1
1442*0b57cec5SDimitry Andric             << getOpenMPClauseName(OMPC_depend);
1443*0b57cec5SDimitry Andric       }
1444*0b57cec5SDimitry Andric       HasAssociatedStatement = false;
1445*0b57cec5SDimitry Andric     }
1446*0b57cec5SDimitry Andric 
1447*0b57cec5SDimitry Andric     StmtResult AssociatedStmt;
1448*0b57cec5SDimitry Andric     if (HasAssociatedStatement) {
1449*0b57cec5SDimitry Andric       // The body is a block scope like in Lambdas and Blocks.
1450*0b57cec5SDimitry Andric       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1451*0b57cec5SDimitry Andric       // FIXME: We create a bogus CompoundStmt scope to hold the contents of
1452*0b57cec5SDimitry Andric       // the captured region. Code elsewhere assumes that any FunctionScopeInfo
1453*0b57cec5SDimitry Andric       // should have at least one compound statement scope within it.
1454*0b57cec5SDimitry Andric       AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
1455*0b57cec5SDimitry Andric       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1456*0b57cec5SDimitry Andric     } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1457*0b57cec5SDimitry Andric                DKind == OMPD_target_exit_data) {
1458*0b57cec5SDimitry Andric       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1459*0b57cec5SDimitry Andric       AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
1460*0b57cec5SDimitry Andric                         Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
1461*0b57cec5SDimitry Andric                                                   /*isStmtExpr=*/false));
1462*0b57cec5SDimitry Andric       AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1463*0b57cec5SDimitry Andric     }
1464*0b57cec5SDimitry Andric     Directive = Actions.ActOnOpenMPExecutableDirective(
1465*0b57cec5SDimitry Andric         DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1466*0b57cec5SDimitry Andric         EndLoc);
1467*0b57cec5SDimitry Andric 
1468*0b57cec5SDimitry Andric     // Exit scope.
1469*0b57cec5SDimitry Andric     Actions.EndOpenMPDSABlock(Directive.get());
1470*0b57cec5SDimitry Andric     OMPDirectiveScope.Exit();
1471*0b57cec5SDimitry Andric     break;
1472*0b57cec5SDimitry Andric   }
1473*0b57cec5SDimitry Andric   case OMPD_declare_simd:
1474*0b57cec5SDimitry Andric   case OMPD_declare_target:
1475*0b57cec5SDimitry Andric   case OMPD_end_declare_target:
1476*0b57cec5SDimitry Andric   case OMPD_requires:
1477*0b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_unexpected_directive)
1478*0b57cec5SDimitry Andric         << 1 << getOpenMPDirectiveName(DKind);
1479*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end);
1480*0b57cec5SDimitry Andric     break;
1481*0b57cec5SDimitry Andric   case OMPD_unknown:
1482*0b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_unknown_directive);
1483*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end);
1484*0b57cec5SDimitry Andric     break;
1485*0b57cec5SDimitry Andric   }
1486*0b57cec5SDimitry Andric   return Directive;
1487*0b57cec5SDimitry Andric }
1488*0b57cec5SDimitry Andric 
1489*0b57cec5SDimitry Andric // Parses simple list:
1490*0b57cec5SDimitry Andric //   simple-variable-list:
1491*0b57cec5SDimitry Andric //         '(' id-expression {, id-expression} ')'
1492*0b57cec5SDimitry Andric //
1493*0b57cec5SDimitry Andric bool Parser::ParseOpenMPSimpleVarList(
1494*0b57cec5SDimitry Andric     OpenMPDirectiveKind Kind,
1495*0b57cec5SDimitry Andric     const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1496*0b57cec5SDimitry Andric         Callback,
1497*0b57cec5SDimitry Andric     bool AllowScopeSpecifier) {
1498*0b57cec5SDimitry Andric   // Parse '('.
1499*0b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1500*0b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
1501*0b57cec5SDimitry Andric                          getOpenMPDirectiveName(Kind)))
1502*0b57cec5SDimitry Andric     return true;
1503*0b57cec5SDimitry Andric   bool IsCorrect = true;
1504*0b57cec5SDimitry Andric   bool NoIdentIsFound = true;
1505*0b57cec5SDimitry Andric 
1506*0b57cec5SDimitry Andric   // Read tokens while ')' or annot_pragma_openmp_end is not found.
1507*0b57cec5SDimitry Andric   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1508*0b57cec5SDimitry Andric     CXXScopeSpec SS;
1509*0b57cec5SDimitry Andric     UnqualifiedId Name;
1510*0b57cec5SDimitry Andric     // Read var name.
1511*0b57cec5SDimitry Andric     Token PrevTok = Tok;
1512*0b57cec5SDimitry Andric     NoIdentIsFound = false;
1513*0b57cec5SDimitry Andric 
1514*0b57cec5SDimitry Andric     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1515*0b57cec5SDimitry Andric         ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1516*0b57cec5SDimitry Andric       IsCorrect = false;
1517*0b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1518*0b57cec5SDimitry Andric                 StopBeforeMatch);
1519*0b57cec5SDimitry Andric     } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
1520*0b57cec5SDimitry Andric                                   nullptr, Name)) {
1521*0b57cec5SDimitry Andric       IsCorrect = false;
1522*0b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1523*0b57cec5SDimitry Andric                 StopBeforeMatch);
1524*0b57cec5SDimitry Andric     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1525*0b57cec5SDimitry Andric                Tok.isNot(tok::annot_pragma_openmp_end)) {
1526*0b57cec5SDimitry Andric       IsCorrect = false;
1527*0b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1528*0b57cec5SDimitry Andric                 StopBeforeMatch);
1529*0b57cec5SDimitry Andric       Diag(PrevTok.getLocation(), diag::err_expected)
1530*0b57cec5SDimitry Andric           << tok::identifier
1531*0b57cec5SDimitry Andric           << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1532*0b57cec5SDimitry Andric     } else {
1533*0b57cec5SDimitry Andric       Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1534*0b57cec5SDimitry Andric     }
1535*0b57cec5SDimitry Andric     // Consume ','.
1536*0b57cec5SDimitry Andric     if (Tok.is(tok::comma)) {
1537*0b57cec5SDimitry Andric       ConsumeToken();
1538*0b57cec5SDimitry Andric     }
1539*0b57cec5SDimitry Andric   }
1540*0b57cec5SDimitry Andric 
1541*0b57cec5SDimitry Andric   if (NoIdentIsFound) {
1542*0b57cec5SDimitry Andric     Diag(Tok, diag::err_expected) << tok::identifier;
1543*0b57cec5SDimitry Andric     IsCorrect = false;
1544*0b57cec5SDimitry Andric   }
1545*0b57cec5SDimitry Andric 
1546*0b57cec5SDimitry Andric   // Parse ')'.
1547*0b57cec5SDimitry Andric   IsCorrect = !T.consumeClose() && IsCorrect;
1548*0b57cec5SDimitry Andric 
1549*0b57cec5SDimitry Andric   return !IsCorrect;
1550*0b57cec5SDimitry Andric }
1551*0b57cec5SDimitry Andric 
1552*0b57cec5SDimitry Andric /// Parsing of OpenMP clauses.
1553*0b57cec5SDimitry Andric ///
1554*0b57cec5SDimitry Andric ///    clause:
1555*0b57cec5SDimitry Andric ///       if-clause | final-clause | num_threads-clause | safelen-clause |
1556*0b57cec5SDimitry Andric ///       default-clause | private-clause | firstprivate-clause | shared-clause
1557*0b57cec5SDimitry Andric ///       | linear-clause | aligned-clause | collapse-clause |
1558*0b57cec5SDimitry Andric ///       lastprivate-clause | reduction-clause | proc_bind-clause |
1559*0b57cec5SDimitry Andric ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1560*0b57cec5SDimitry Andric ///       mergeable-clause | flush-clause | read-clause | write-clause |
1561*0b57cec5SDimitry Andric ///       update-clause | capture-clause | seq_cst-clause | device-clause |
1562*0b57cec5SDimitry Andric ///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1563*0b57cec5SDimitry Andric ///       thread_limit-clause | priority-clause | grainsize-clause |
1564*0b57cec5SDimitry Andric ///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1565*0b57cec5SDimitry Andric ///       from-clause | is_device_ptr-clause | task_reduction-clause |
1566*0b57cec5SDimitry Andric ///       in_reduction-clause | allocator-clause | allocate-clause
1567*0b57cec5SDimitry Andric ///
1568*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1569*0b57cec5SDimitry Andric                                      OpenMPClauseKind CKind, bool FirstClause) {
1570*0b57cec5SDimitry Andric   OMPClause *Clause = nullptr;
1571*0b57cec5SDimitry Andric   bool ErrorFound = false;
1572*0b57cec5SDimitry Andric   bool WrongDirective = false;
1573*0b57cec5SDimitry Andric   // Check if clause is allowed for the given directive.
1574*0b57cec5SDimitry Andric   if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1575*0b57cec5SDimitry Andric     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1576*0b57cec5SDimitry Andric                                                << getOpenMPDirectiveName(DKind);
1577*0b57cec5SDimitry Andric     ErrorFound = true;
1578*0b57cec5SDimitry Andric     WrongDirective = true;
1579*0b57cec5SDimitry Andric   }
1580*0b57cec5SDimitry Andric 
1581*0b57cec5SDimitry Andric   switch (CKind) {
1582*0b57cec5SDimitry Andric   case OMPC_final:
1583*0b57cec5SDimitry Andric   case OMPC_num_threads:
1584*0b57cec5SDimitry Andric   case OMPC_safelen:
1585*0b57cec5SDimitry Andric   case OMPC_simdlen:
1586*0b57cec5SDimitry Andric   case OMPC_collapse:
1587*0b57cec5SDimitry Andric   case OMPC_ordered:
1588*0b57cec5SDimitry Andric   case OMPC_device:
1589*0b57cec5SDimitry Andric   case OMPC_num_teams:
1590*0b57cec5SDimitry Andric   case OMPC_thread_limit:
1591*0b57cec5SDimitry Andric   case OMPC_priority:
1592*0b57cec5SDimitry Andric   case OMPC_grainsize:
1593*0b57cec5SDimitry Andric   case OMPC_num_tasks:
1594*0b57cec5SDimitry Andric   case OMPC_hint:
1595*0b57cec5SDimitry Andric   case OMPC_allocator:
1596*0b57cec5SDimitry Andric     // OpenMP [2.5, Restrictions]
1597*0b57cec5SDimitry Andric     //  At most one num_threads clause can appear on the directive.
1598*0b57cec5SDimitry Andric     // OpenMP [2.8.1, simd construct, Restrictions]
1599*0b57cec5SDimitry Andric     //  Only one safelen  clause can appear on a simd directive.
1600*0b57cec5SDimitry Andric     //  Only one simdlen  clause can appear on a simd directive.
1601*0b57cec5SDimitry Andric     //  Only one collapse clause can appear on a simd directive.
1602*0b57cec5SDimitry Andric     // OpenMP [2.9.1, target data construct, Restrictions]
1603*0b57cec5SDimitry Andric     //  At most one device clause can appear on the directive.
1604*0b57cec5SDimitry Andric     // OpenMP [2.11.1, task Construct, Restrictions]
1605*0b57cec5SDimitry Andric     //  At most one if clause can appear on the directive.
1606*0b57cec5SDimitry Andric     //  At most one final clause can appear on the directive.
1607*0b57cec5SDimitry Andric     // OpenMP [teams Construct, Restrictions]
1608*0b57cec5SDimitry Andric     //  At most one num_teams clause can appear on the directive.
1609*0b57cec5SDimitry Andric     //  At most one thread_limit clause can appear on the directive.
1610*0b57cec5SDimitry Andric     // OpenMP [2.9.1, task Construct, Restrictions]
1611*0b57cec5SDimitry Andric     // At most one priority clause can appear on the directive.
1612*0b57cec5SDimitry Andric     // OpenMP [2.9.2, taskloop Construct, Restrictions]
1613*0b57cec5SDimitry Andric     // At most one grainsize clause can appear on the directive.
1614*0b57cec5SDimitry Andric     // OpenMP [2.9.2, taskloop Construct, Restrictions]
1615*0b57cec5SDimitry Andric     // At most one num_tasks clause can appear on the directive.
1616*0b57cec5SDimitry Andric     // OpenMP [2.11.3, allocate Directive, Restrictions]
1617*0b57cec5SDimitry Andric     // At most one allocator clause can appear on the directive.
1618*0b57cec5SDimitry Andric     if (!FirstClause) {
1619*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
1620*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1621*0b57cec5SDimitry Andric       ErrorFound = true;
1622*0b57cec5SDimitry Andric     }
1623*0b57cec5SDimitry Andric 
1624*0b57cec5SDimitry Andric     if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1625*0b57cec5SDimitry Andric       Clause = ParseOpenMPClause(CKind, WrongDirective);
1626*0b57cec5SDimitry Andric     else
1627*0b57cec5SDimitry Andric       Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
1628*0b57cec5SDimitry Andric     break;
1629*0b57cec5SDimitry Andric   case OMPC_default:
1630*0b57cec5SDimitry Andric   case OMPC_proc_bind:
1631*0b57cec5SDimitry Andric   case OMPC_atomic_default_mem_order:
1632*0b57cec5SDimitry Andric     // OpenMP [2.14.3.1, Restrictions]
1633*0b57cec5SDimitry Andric     //  Only a single default clause may be specified on a parallel, task or
1634*0b57cec5SDimitry Andric     //  teams directive.
1635*0b57cec5SDimitry Andric     // OpenMP [2.5, parallel Construct, Restrictions]
1636*0b57cec5SDimitry Andric     //  At most one proc_bind clause can appear on the directive.
1637*0b57cec5SDimitry Andric     // OpenMP [5.0, Requires directive, Restrictions]
1638*0b57cec5SDimitry Andric     //  At most one atomic_default_mem_order clause can appear
1639*0b57cec5SDimitry Andric     //  on the directive
1640*0b57cec5SDimitry Andric     if (!FirstClause) {
1641*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
1642*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1643*0b57cec5SDimitry Andric       ErrorFound = true;
1644*0b57cec5SDimitry Andric     }
1645*0b57cec5SDimitry Andric 
1646*0b57cec5SDimitry Andric     Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
1647*0b57cec5SDimitry Andric     break;
1648*0b57cec5SDimitry Andric   case OMPC_schedule:
1649*0b57cec5SDimitry Andric   case OMPC_dist_schedule:
1650*0b57cec5SDimitry Andric   case OMPC_defaultmap:
1651*0b57cec5SDimitry Andric     // OpenMP [2.7.1, Restrictions, p. 3]
1652*0b57cec5SDimitry Andric     //  Only one schedule clause can appear on a loop directive.
1653*0b57cec5SDimitry Andric     // OpenMP [2.10.4, Restrictions, p. 106]
1654*0b57cec5SDimitry Andric     //  At most one defaultmap clause can appear on the directive.
1655*0b57cec5SDimitry Andric     if (!FirstClause) {
1656*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
1657*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1658*0b57cec5SDimitry Andric       ErrorFound = true;
1659*0b57cec5SDimitry Andric     }
1660*0b57cec5SDimitry Andric     LLVM_FALLTHROUGH;
1661*0b57cec5SDimitry Andric 
1662*0b57cec5SDimitry Andric   case OMPC_if:
1663*0b57cec5SDimitry Andric     Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
1664*0b57cec5SDimitry Andric     break;
1665*0b57cec5SDimitry Andric   case OMPC_nowait:
1666*0b57cec5SDimitry Andric   case OMPC_untied:
1667*0b57cec5SDimitry Andric   case OMPC_mergeable:
1668*0b57cec5SDimitry Andric   case OMPC_read:
1669*0b57cec5SDimitry Andric   case OMPC_write:
1670*0b57cec5SDimitry Andric   case OMPC_update:
1671*0b57cec5SDimitry Andric   case OMPC_capture:
1672*0b57cec5SDimitry Andric   case OMPC_seq_cst:
1673*0b57cec5SDimitry Andric   case OMPC_threads:
1674*0b57cec5SDimitry Andric   case OMPC_simd:
1675*0b57cec5SDimitry Andric   case OMPC_nogroup:
1676*0b57cec5SDimitry Andric   case OMPC_unified_address:
1677*0b57cec5SDimitry Andric   case OMPC_unified_shared_memory:
1678*0b57cec5SDimitry Andric   case OMPC_reverse_offload:
1679*0b57cec5SDimitry Andric   case OMPC_dynamic_allocators:
1680*0b57cec5SDimitry Andric     // OpenMP [2.7.1, Restrictions, p. 9]
1681*0b57cec5SDimitry Andric     //  Only one ordered clause can appear on a loop directive.
1682*0b57cec5SDimitry Andric     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1683*0b57cec5SDimitry Andric     //  Only one nowait clause can appear on a for directive.
1684*0b57cec5SDimitry Andric     // OpenMP [5.0, Requires directive, Restrictions]
1685*0b57cec5SDimitry Andric     //   Each of the requires clauses can appear at most once on the directive.
1686*0b57cec5SDimitry Andric     if (!FirstClause) {
1687*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_more_one_clause)
1688*0b57cec5SDimitry Andric           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1689*0b57cec5SDimitry Andric       ErrorFound = true;
1690*0b57cec5SDimitry Andric     }
1691*0b57cec5SDimitry Andric 
1692*0b57cec5SDimitry Andric     Clause = ParseOpenMPClause(CKind, WrongDirective);
1693*0b57cec5SDimitry Andric     break;
1694*0b57cec5SDimitry Andric   case OMPC_private:
1695*0b57cec5SDimitry Andric   case OMPC_firstprivate:
1696*0b57cec5SDimitry Andric   case OMPC_lastprivate:
1697*0b57cec5SDimitry Andric   case OMPC_shared:
1698*0b57cec5SDimitry Andric   case OMPC_reduction:
1699*0b57cec5SDimitry Andric   case OMPC_task_reduction:
1700*0b57cec5SDimitry Andric   case OMPC_in_reduction:
1701*0b57cec5SDimitry Andric   case OMPC_linear:
1702*0b57cec5SDimitry Andric   case OMPC_aligned:
1703*0b57cec5SDimitry Andric   case OMPC_copyin:
1704*0b57cec5SDimitry Andric   case OMPC_copyprivate:
1705*0b57cec5SDimitry Andric   case OMPC_flush:
1706*0b57cec5SDimitry Andric   case OMPC_depend:
1707*0b57cec5SDimitry Andric   case OMPC_map:
1708*0b57cec5SDimitry Andric   case OMPC_to:
1709*0b57cec5SDimitry Andric   case OMPC_from:
1710*0b57cec5SDimitry Andric   case OMPC_use_device_ptr:
1711*0b57cec5SDimitry Andric   case OMPC_is_device_ptr:
1712*0b57cec5SDimitry Andric   case OMPC_allocate:
1713*0b57cec5SDimitry Andric     Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
1714*0b57cec5SDimitry Andric     break;
1715*0b57cec5SDimitry Andric   case OMPC_unknown:
1716*0b57cec5SDimitry Andric     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1717*0b57cec5SDimitry Andric         << getOpenMPDirectiveName(DKind);
1718*0b57cec5SDimitry Andric     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1719*0b57cec5SDimitry Andric     break;
1720*0b57cec5SDimitry Andric   case OMPC_threadprivate:
1721*0b57cec5SDimitry Andric   case OMPC_uniform:
1722*0b57cec5SDimitry Andric     if (!WrongDirective)
1723*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_unexpected_clause)
1724*0b57cec5SDimitry Andric           << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
1725*0b57cec5SDimitry Andric     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1726*0b57cec5SDimitry Andric     break;
1727*0b57cec5SDimitry Andric   }
1728*0b57cec5SDimitry Andric   return ErrorFound ? nullptr : Clause;
1729*0b57cec5SDimitry Andric }
1730*0b57cec5SDimitry Andric 
1731*0b57cec5SDimitry Andric /// Parses simple expression in parens for single-expression clauses of OpenMP
1732*0b57cec5SDimitry Andric /// constructs.
1733*0b57cec5SDimitry Andric /// \param RLoc Returned location of right paren.
1734*0b57cec5SDimitry Andric ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
1735*0b57cec5SDimitry Andric                                          SourceLocation &RLoc) {
1736*0b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1737*0b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1738*0b57cec5SDimitry Andric     return ExprError();
1739*0b57cec5SDimitry Andric 
1740*0b57cec5SDimitry Andric   SourceLocation ELoc = Tok.getLocation();
1741*0b57cec5SDimitry Andric   ExprResult LHS(ParseCastExpression(
1742*0b57cec5SDimitry Andric       /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1743*0b57cec5SDimitry Andric   ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1744*0b57cec5SDimitry Andric   Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
1745*0b57cec5SDimitry Andric 
1746*0b57cec5SDimitry Andric   // Parse ')'.
1747*0b57cec5SDimitry Andric   RLoc = Tok.getLocation();
1748*0b57cec5SDimitry Andric   if (!T.consumeClose())
1749*0b57cec5SDimitry Andric     RLoc = T.getCloseLocation();
1750*0b57cec5SDimitry Andric 
1751*0b57cec5SDimitry Andric   return Val;
1752*0b57cec5SDimitry Andric }
1753*0b57cec5SDimitry Andric 
1754*0b57cec5SDimitry Andric /// Parsing of OpenMP clauses with single expressions like 'final',
1755*0b57cec5SDimitry Andric /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1756*0b57cec5SDimitry Andric /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1757*0b57cec5SDimitry Andric ///
1758*0b57cec5SDimitry Andric ///    final-clause:
1759*0b57cec5SDimitry Andric ///      'final' '(' expression ')'
1760*0b57cec5SDimitry Andric ///
1761*0b57cec5SDimitry Andric ///    num_threads-clause:
1762*0b57cec5SDimitry Andric ///      'num_threads' '(' expression ')'
1763*0b57cec5SDimitry Andric ///
1764*0b57cec5SDimitry Andric ///    safelen-clause:
1765*0b57cec5SDimitry Andric ///      'safelen' '(' expression ')'
1766*0b57cec5SDimitry Andric ///
1767*0b57cec5SDimitry Andric ///    simdlen-clause:
1768*0b57cec5SDimitry Andric ///      'simdlen' '(' expression ')'
1769*0b57cec5SDimitry Andric ///
1770*0b57cec5SDimitry Andric ///    collapse-clause:
1771*0b57cec5SDimitry Andric ///      'collapse' '(' expression ')'
1772*0b57cec5SDimitry Andric ///
1773*0b57cec5SDimitry Andric ///    priority-clause:
1774*0b57cec5SDimitry Andric ///      'priority' '(' expression ')'
1775*0b57cec5SDimitry Andric ///
1776*0b57cec5SDimitry Andric ///    grainsize-clause:
1777*0b57cec5SDimitry Andric ///      'grainsize' '(' expression ')'
1778*0b57cec5SDimitry Andric ///
1779*0b57cec5SDimitry Andric ///    num_tasks-clause:
1780*0b57cec5SDimitry Andric ///      'num_tasks' '(' expression ')'
1781*0b57cec5SDimitry Andric ///
1782*0b57cec5SDimitry Andric ///    hint-clause:
1783*0b57cec5SDimitry Andric ///      'hint' '(' expression ')'
1784*0b57cec5SDimitry Andric ///
1785*0b57cec5SDimitry Andric ///    allocator-clause:
1786*0b57cec5SDimitry Andric ///      'allocator' '(' expression ')'
1787*0b57cec5SDimitry Andric ///
1788*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
1789*0b57cec5SDimitry Andric                                                bool ParseOnly) {
1790*0b57cec5SDimitry Andric   SourceLocation Loc = ConsumeToken();
1791*0b57cec5SDimitry Andric   SourceLocation LLoc = Tok.getLocation();
1792*0b57cec5SDimitry Andric   SourceLocation RLoc;
1793*0b57cec5SDimitry Andric 
1794*0b57cec5SDimitry Andric   ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1795*0b57cec5SDimitry Andric 
1796*0b57cec5SDimitry Andric   if (Val.isInvalid())
1797*0b57cec5SDimitry Andric     return nullptr;
1798*0b57cec5SDimitry Andric 
1799*0b57cec5SDimitry Andric   if (ParseOnly)
1800*0b57cec5SDimitry Andric     return nullptr;
1801*0b57cec5SDimitry Andric   return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1802*0b57cec5SDimitry Andric }
1803*0b57cec5SDimitry Andric 
1804*0b57cec5SDimitry Andric /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1805*0b57cec5SDimitry Andric ///
1806*0b57cec5SDimitry Andric ///    default-clause:
1807*0b57cec5SDimitry Andric ///         'default' '(' 'none' | 'shared' ')
1808*0b57cec5SDimitry Andric ///
1809*0b57cec5SDimitry Andric ///    proc_bind-clause:
1810*0b57cec5SDimitry Andric ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
1811*0b57cec5SDimitry Andric ///
1812*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
1813*0b57cec5SDimitry Andric                                            bool ParseOnly) {
1814*0b57cec5SDimitry Andric   SourceLocation Loc = Tok.getLocation();
1815*0b57cec5SDimitry Andric   SourceLocation LOpen = ConsumeToken();
1816*0b57cec5SDimitry Andric   // Parse '('.
1817*0b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1818*0b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
1819*0b57cec5SDimitry Andric                          getOpenMPClauseName(Kind)))
1820*0b57cec5SDimitry Andric     return nullptr;
1821*0b57cec5SDimitry Andric 
1822*0b57cec5SDimitry Andric   unsigned Type = getOpenMPSimpleClauseType(
1823*0b57cec5SDimitry Andric       Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1824*0b57cec5SDimitry Andric   SourceLocation TypeLoc = Tok.getLocation();
1825*0b57cec5SDimitry Andric   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1826*0b57cec5SDimitry Andric       Tok.isNot(tok::annot_pragma_openmp_end))
1827*0b57cec5SDimitry Andric     ConsumeAnyToken();
1828*0b57cec5SDimitry Andric 
1829*0b57cec5SDimitry Andric   // Parse ')'.
1830*0b57cec5SDimitry Andric   SourceLocation RLoc = Tok.getLocation();
1831*0b57cec5SDimitry Andric   if (!T.consumeClose())
1832*0b57cec5SDimitry Andric     RLoc = T.getCloseLocation();
1833*0b57cec5SDimitry Andric 
1834*0b57cec5SDimitry Andric   if (ParseOnly)
1835*0b57cec5SDimitry Andric     return nullptr;
1836*0b57cec5SDimitry Andric   return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc);
1837*0b57cec5SDimitry Andric }
1838*0b57cec5SDimitry Andric 
1839*0b57cec5SDimitry Andric /// Parsing of OpenMP clauses like 'ordered'.
1840*0b57cec5SDimitry Andric ///
1841*0b57cec5SDimitry Andric ///    ordered-clause:
1842*0b57cec5SDimitry Andric ///         'ordered'
1843*0b57cec5SDimitry Andric ///
1844*0b57cec5SDimitry Andric ///    nowait-clause:
1845*0b57cec5SDimitry Andric ///         'nowait'
1846*0b57cec5SDimitry Andric ///
1847*0b57cec5SDimitry Andric ///    untied-clause:
1848*0b57cec5SDimitry Andric ///         'untied'
1849*0b57cec5SDimitry Andric ///
1850*0b57cec5SDimitry Andric ///    mergeable-clause:
1851*0b57cec5SDimitry Andric ///         'mergeable'
1852*0b57cec5SDimitry Andric ///
1853*0b57cec5SDimitry Andric ///    read-clause:
1854*0b57cec5SDimitry Andric ///         'read'
1855*0b57cec5SDimitry Andric ///
1856*0b57cec5SDimitry Andric ///    threads-clause:
1857*0b57cec5SDimitry Andric ///         'threads'
1858*0b57cec5SDimitry Andric ///
1859*0b57cec5SDimitry Andric ///    simd-clause:
1860*0b57cec5SDimitry Andric ///         'simd'
1861*0b57cec5SDimitry Andric ///
1862*0b57cec5SDimitry Andric ///    nogroup-clause:
1863*0b57cec5SDimitry Andric ///         'nogroup'
1864*0b57cec5SDimitry Andric ///
1865*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
1866*0b57cec5SDimitry Andric   SourceLocation Loc = Tok.getLocation();
1867*0b57cec5SDimitry Andric   ConsumeAnyToken();
1868*0b57cec5SDimitry Andric 
1869*0b57cec5SDimitry Andric   if (ParseOnly)
1870*0b57cec5SDimitry Andric     return nullptr;
1871*0b57cec5SDimitry Andric   return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1872*0b57cec5SDimitry Andric }
1873*0b57cec5SDimitry Andric 
1874*0b57cec5SDimitry Andric 
1875*0b57cec5SDimitry Andric /// Parsing of OpenMP clauses with single expressions and some additional
1876*0b57cec5SDimitry Andric /// argument like 'schedule' or 'dist_schedule'.
1877*0b57cec5SDimitry Andric ///
1878*0b57cec5SDimitry Andric ///    schedule-clause:
1879*0b57cec5SDimitry Andric ///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1880*0b57cec5SDimitry Andric ///      ')'
1881*0b57cec5SDimitry Andric ///
1882*0b57cec5SDimitry Andric ///    if-clause:
1883*0b57cec5SDimitry Andric ///      'if' '(' [ directive-name-modifier ':' ] expression ')'
1884*0b57cec5SDimitry Andric ///
1885*0b57cec5SDimitry Andric ///    defaultmap:
1886*0b57cec5SDimitry Andric ///      'defaultmap' '(' modifier ':' kind ')'
1887*0b57cec5SDimitry Andric ///
1888*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
1889*0b57cec5SDimitry Andric                                                       bool ParseOnly) {
1890*0b57cec5SDimitry Andric   SourceLocation Loc = ConsumeToken();
1891*0b57cec5SDimitry Andric   SourceLocation DelimLoc;
1892*0b57cec5SDimitry Andric   // Parse '('.
1893*0b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1894*0b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
1895*0b57cec5SDimitry Andric                          getOpenMPClauseName(Kind)))
1896*0b57cec5SDimitry Andric     return nullptr;
1897*0b57cec5SDimitry Andric 
1898*0b57cec5SDimitry Andric   ExprResult Val;
1899*0b57cec5SDimitry Andric   SmallVector<unsigned, 4> Arg;
1900*0b57cec5SDimitry Andric   SmallVector<SourceLocation, 4> KLoc;
1901*0b57cec5SDimitry Andric   if (Kind == OMPC_schedule) {
1902*0b57cec5SDimitry Andric     enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1903*0b57cec5SDimitry Andric     Arg.resize(NumberOfElements);
1904*0b57cec5SDimitry Andric     KLoc.resize(NumberOfElements);
1905*0b57cec5SDimitry Andric     Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1906*0b57cec5SDimitry Andric     Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1907*0b57cec5SDimitry Andric     Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1908*0b57cec5SDimitry Andric     unsigned KindModifier = getOpenMPSimpleClauseType(
1909*0b57cec5SDimitry Andric         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1910*0b57cec5SDimitry Andric     if (KindModifier > OMPC_SCHEDULE_unknown) {
1911*0b57cec5SDimitry Andric       // Parse 'modifier'
1912*0b57cec5SDimitry Andric       Arg[Modifier1] = KindModifier;
1913*0b57cec5SDimitry Andric       KLoc[Modifier1] = Tok.getLocation();
1914*0b57cec5SDimitry Andric       if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1915*0b57cec5SDimitry Andric           Tok.isNot(tok::annot_pragma_openmp_end))
1916*0b57cec5SDimitry Andric         ConsumeAnyToken();
1917*0b57cec5SDimitry Andric       if (Tok.is(tok::comma)) {
1918*0b57cec5SDimitry Andric         // Parse ',' 'modifier'
1919*0b57cec5SDimitry Andric         ConsumeAnyToken();
1920*0b57cec5SDimitry Andric         KindModifier = getOpenMPSimpleClauseType(
1921*0b57cec5SDimitry Andric             Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1922*0b57cec5SDimitry Andric         Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1923*0b57cec5SDimitry Andric                              ? KindModifier
1924*0b57cec5SDimitry Andric                              : (unsigned)OMPC_SCHEDULE_unknown;
1925*0b57cec5SDimitry Andric         KLoc[Modifier2] = Tok.getLocation();
1926*0b57cec5SDimitry Andric         if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1927*0b57cec5SDimitry Andric             Tok.isNot(tok::annot_pragma_openmp_end))
1928*0b57cec5SDimitry Andric           ConsumeAnyToken();
1929*0b57cec5SDimitry Andric       }
1930*0b57cec5SDimitry Andric       // Parse ':'
1931*0b57cec5SDimitry Andric       if (Tok.is(tok::colon))
1932*0b57cec5SDimitry Andric         ConsumeAnyToken();
1933*0b57cec5SDimitry Andric       else
1934*0b57cec5SDimitry Andric         Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1935*0b57cec5SDimitry Andric       KindModifier = getOpenMPSimpleClauseType(
1936*0b57cec5SDimitry Andric           Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1937*0b57cec5SDimitry Andric     }
1938*0b57cec5SDimitry Andric     Arg[ScheduleKind] = KindModifier;
1939*0b57cec5SDimitry Andric     KLoc[ScheduleKind] = Tok.getLocation();
1940*0b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1941*0b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end))
1942*0b57cec5SDimitry Andric       ConsumeAnyToken();
1943*0b57cec5SDimitry Andric     if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1944*0b57cec5SDimitry Andric          Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1945*0b57cec5SDimitry Andric          Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1946*0b57cec5SDimitry Andric         Tok.is(tok::comma))
1947*0b57cec5SDimitry Andric       DelimLoc = ConsumeAnyToken();
1948*0b57cec5SDimitry Andric   } else if (Kind == OMPC_dist_schedule) {
1949*0b57cec5SDimitry Andric     Arg.push_back(getOpenMPSimpleClauseType(
1950*0b57cec5SDimitry Andric         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1951*0b57cec5SDimitry Andric     KLoc.push_back(Tok.getLocation());
1952*0b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1953*0b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end))
1954*0b57cec5SDimitry Andric       ConsumeAnyToken();
1955*0b57cec5SDimitry Andric     if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1956*0b57cec5SDimitry Andric       DelimLoc = ConsumeAnyToken();
1957*0b57cec5SDimitry Andric   } else if (Kind == OMPC_defaultmap) {
1958*0b57cec5SDimitry Andric     // Get a defaultmap modifier
1959*0b57cec5SDimitry Andric     Arg.push_back(getOpenMPSimpleClauseType(
1960*0b57cec5SDimitry Andric         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1961*0b57cec5SDimitry Andric     KLoc.push_back(Tok.getLocation());
1962*0b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1963*0b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end))
1964*0b57cec5SDimitry Andric       ConsumeAnyToken();
1965*0b57cec5SDimitry Andric     // Parse ':'
1966*0b57cec5SDimitry Andric     if (Tok.is(tok::colon))
1967*0b57cec5SDimitry Andric       ConsumeAnyToken();
1968*0b57cec5SDimitry Andric     else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1969*0b57cec5SDimitry Andric       Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1970*0b57cec5SDimitry Andric     // Get a defaultmap kind
1971*0b57cec5SDimitry Andric     Arg.push_back(getOpenMPSimpleClauseType(
1972*0b57cec5SDimitry Andric         Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1973*0b57cec5SDimitry Andric     KLoc.push_back(Tok.getLocation());
1974*0b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1975*0b57cec5SDimitry Andric         Tok.isNot(tok::annot_pragma_openmp_end))
1976*0b57cec5SDimitry Andric       ConsumeAnyToken();
1977*0b57cec5SDimitry Andric   } else {
1978*0b57cec5SDimitry Andric     assert(Kind == OMPC_if);
1979*0b57cec5SDimitry Andric     KLoc.push_back(Tok.getLocation());
1980*0b57cec5SDimitry Andric     TentativeParsingAction TPA(*this);
1981*0b57cec5SDimitry Andric     Arg.push_back(parseOpenMPDirectiveKind(*this));
1982*0b57cec5SDimitry Andric     if (Arg.back() != OMPD_unknown) {
1983*0b57cec5SDimitry Andric       ConsumeToken();
1984*0b57cec5SDimitry Andric       if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1985*0b57cec5SDimitry Andric         TPA.Commit();
1986*0b57cec5SDimitry Andric         DelimLoc = ConsumeToken();
1987*0b57cec5SDimitry Andric       } else {
1988*0b57cec5SDimitry Andric         TPA.Revert();
1989*0b57cec5SDimitry Andric         Arg.back() = OMPD_unknown;
1990*0b57cec5SDimitry Andric       }
1991*0b57cec5SDimitry Andric     } else {
1992*0b57cec5SDimitry Andric       TPA.Revert();
1993*0b57cec5SDimitry Andric     }
1994*0b57cec5SDimitry Andric   }
1995*0b57cec5SDimitry Andric 
1996*0b57cec5SDimitry Andric   bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1997*0b57cec5SDimitry Andric                           (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1998*0b57cec5SDimitry Andric                           Kind == OMPC_if;
1999*0b57cec5SDimitry Andric   if (NeedAnExpression) {
2000*0b57cec5SDimitry Andric     SourceLocation ELoc = Tok.getLocation();
2001*0b57cec5SDimitry Andric     ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
2002*0b57cec5SDimitry Andric     Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
2003*0b57cec5SDimitry Andric     Val =
2004*0b57cec5SDimitry Andric         Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
2005*0b57cec5SDimitry Andric   }
2006*0b57cec5SDimitry Andric 
2007*0b57cec5SDimitry Andric   // Parse ')'.
2008*0b57cec5SDimitry Andric   SourceLocation RLoc = Tok.getLocation();
2009*0b57cec5SDimitry Andric   if (!T.consumeClose())
2010*0b57cec5SDimitry Andric     RLoc = T.getCloseLocation();
2011*0b57cec5SDimitry Andric 
2012*0b57cec5SDimitry Andric   if (NeedAnExpression && Val.isInvalid())
2013*0b57cec5SDimitry Andric     return nullptr;
2014*0b57cec5SDimitry Andric 
2015*0b57cec5SDimitry Andric   if (ParseOnly)
2016*0b57cec5SDimitry Andric     return nullptr;
2017*0b57cec5SDimitry Andric   return Actions.ActOnOpenMPSingleExprWithArgClause(
2018*0b57cec5SDimitry Andric       Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
2019*0b57cec5SDimitry Andric }
2020*0b57cec5SDimitry Andric 
2021*0b57cec5SDimitry Andric static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
2022*0b57cec5SDimitry Andric                              UnqualifiedId &ReductionId) {
2023*0b57cec5SDimitry Andric   if (ReductionIdScopeSpec.isEmpty()) {
2024*0b57cec5SDimitry Andric     auto OOK = OO_None;
2025*0b57cec5SDimitry Andric     switch (P.getCurToken().getKind()) {
2026*0b57cec5SDimitry Andric     case tok::plus:
2027*0b57cec5SDimitry Andric       OOK = OO_Plus;
2028*0b57cec5SDimitry Andric       break;
2029*0b57cec5SDimitry Andric     case tok::minus:
2030*0b57cec5SDimitry Andric       OOK = OO_Minus;
2031*0b57cec5SDimitry Andric       break;
2032*0b57cec5SDimitry Andric     case tok::star:
2033*0b57cec5SDimitry Andric       OOK = OO_Star;
2034*0b57cec5SDimitry Andric       break;
2035*0b57cec5SDimitry Andric     case tok::amp:
2036*0b57cec5SDimitry Andric       OOK = OO_Amp;
2037*0b57cec5SDimitry Andric       break;
2038*0b57cec5SDimitry Andric     case tok::pipe:
2039*0b57cec5SDimitry Andric       OOK = OO_Pipe;
2040*0b57cec5SDimitry Andric       break;
2041*0b57cec5SDimitry Andric     case tok::caret:
2042*0b57cec5SDimitry Andric       OOK = OO_Caret;
2043*0b57cec5SDimitry Andric       break;
2044*0b57cec5SDimitry Andric     case tok::ampamp:
2045*0b57cec5SDimitry Andric       OOK = OO_AmpAmp;
2046*0b57cec5SDimitry Andric       break;
2047*0b57cec5SDimitry Andric     case tok::pipepipe:
2048*0b57cec5SDimitry Andric       OOK = OO_PipePipe;
2049*0b57cec5SDimitry Andric       break;
2050*0b57cec5SDimitry Andric     default:
2051*0b57cec5SDimitry Andric       break;
2052*0b57cec5SDimitry Andric     }
2053*0b57cec5SDimitry Andric     if (OOK != OO_None) {
2054*0b57cec5SDimitry Andric       SourceLocation OpLoc = P.ConsumeToken();
2055*0b57cec5SDimitry Andric       SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
2056*0b57cec5SDimitry Andric       ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
2057*0b57cec5SDimitry Andric       return false;
2058*0b57cec5SDimitry Andric     }
2059*0b57cec5SDimitry Andric   }
2060*0b57cec5SDimitry Andric   return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
2061*0b57cec5SDimitry Andric                               /*AllowDestructorName*/ false,
2062*0b57cec5SDimitry Andric                               /*AllowConstructorName*/ false,
2063*0b57cec5SDimitry Andric                               /*AllowDeductionGuide*/ false,
2064*0b57cec5SDimitry Andric                               nullptr, nullptr, ReductionId);
2065*0b57cec5SDimitry Andric }
2066*0b57cec5SDimitry Andric 
2067*0b57cec5SDimitry Andric /// Checks if the token is a valid map-type-modifier.
2068*0b57cec5SDimitry Andric static OpenMPMapModifierKind isMapModifier(Parser &P) {
2069*0b57cec5SDimitry Andric   Token Tok = P.getCurToken();
2070*0b57cec5SDimitry Andric   if (!Tok.is(tok::identifier))
2071*0b57cec5SDimitry Andric     return OMPC_MAP_MODIFIER_unknown;
2072*0b57cec5SDimitry Andric 
2073*0b57cec5SDimitry Andric   Preprocessor &PP = P.getPreprocessor();
2074*0b57cec5SDimitry Andric   OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
2075*0b57cec5SDimitry Andric       getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2076*0b57cec5SDimitry Andric   return TypeModifier;
2077*0b57cec5SDimitry Andric }
2078*0b57cec5SDimitry Andric 
2079*0b57cec5SDimitry Andric /// Parse the mapper modifier in map, to, and from clauses.
2080*0b57cec5SDimitry Andric bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
2081*0b57cec5SDimitry Andric   // Parse '('.
2082*0b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
2083*0b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
2084*0b57cec5SDimitry Andric     SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2085*0b57cec5SDimitry Andric               StopBeforeMatch);
2086*0b57cec5SDimitry Andric     return true;
2087*0b57cec5SDimitry Andric   }
2088*0b57cec5SDimitry Andric   // Parse mapper-identifier
2089*0b57cec5SDimitry Andric   if (getLangOpts().CPlusPlus)
2090*0b57cec5SDimitry Andric     ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2091*0b57cec5SDimitry Andric                                    /*ObjectType=*/nullptr,
2092*0b57cec5SDimitry Andric                                    /*EnteringContext=*/false);
2093*0b57cec5SDimitry Andric   if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
2094*0b57cec5SDimitry Andric     Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
2095*0b57cec5SDimitry Andric     SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2096*0b57cec5SDimitry Andric               StopBeforeMatch);
2097*0b57cec5SDimitry Andric     return true;
2098*0b57cec5SDimitry Andric   }
2099*0b57cec5SDimitry Andric   auto &DeclNames = Actions.getASTContext().DeclarationNames;
2100*0b57cec5SDimitry Andric   Data.ReductionOrMapperId = DeclarationNameInfo(
2101*0b57cec5SDimitry Andric       DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
2102*0b57cec5SDimitry Andric   ConsumeToken();
2103*0b57cec5SDimitry Andric   // Parse ')'.
2104*0b57cec5SDimitry Andric   return T.consumeClose();
2105*0b57cec5SDimitry Andric }
2106*0b57cec5SDimitry Andric 
2107*0b57cec5SDimitry Andric /// Parse map-type-modifiers in map clause.
2108*0b57cec5SDimitry Andric /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2109*0b57cec5SDimitry Andric /// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
2110*0b57cec5SDimitry Andric bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
2111*0b57cec5SDimitry Andric   while (getCurToken().isNot(tok::colon)) {
2112*0b57cec5SDimitry Andric     OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
2113*0b57cec5SDimitry Andric     if (TypeModifier == OMPC_MAP_MODIFIER_always ||
2114*0b57cec5SDimitry Andric         TypeModifier == OMPC_MAP_MODIFIER_close) {
2115*0b57cec5SDimitry Andric       Data.MapTypeModifiers.push_back(TypeModifier);
2116*0b57cec5SDimitry Andric       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2117*0b57cec5SDimitry Andric       ConsumeToken();
2118*0b57cec5SDimitry Andric     } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
2119*0b57cec5SDimitry Andric       Data.MapTypeModifiers.push_back(TypeModifier);
2120*0b57cec5SDimitry Andric       Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
2121*0b57cec5SDimitry Andric       ConsumeToken();
2122*0b57cec5SDimitry Andric       if (parseMapperModifier(Data))
2123*0b57cec5SDimitry Andric         return true;
2124*0b57cec5SDimitry Andric     } else {
2125*0b57cec5SDimitry Andric       // For the case of unknown map-type-modifier or a map-type.
2126*0b57cec5SDimitry Andric       // Map-type is followed by a colon; the function returns when it
2127*0b57cec5SDimitry Andric       // encounters a token followed by a colon.
2128*0b57cec5SDimitry Andric       if (Tok.is(tok::comma)) {
2129*0b57cec5SDimitry Andric         Diag(Tok, diag::err_omp_map_type_modifier_missing);
2130*0b57cec5SDimitry Andric         ConsumeToken();
2131*0b57cec5SDimitry Andric         continue;
2132*0b57cec5SDimitry Andric       }
2133*0b57cec5SDimitry Andric       // Potential map-type token as it is followed by a colon.
2134*0b57cec5SDimitry Andric       if (PP.LookAhead(0).is(tok::colon))
2135*0b57cec5SDimitry Andric         return false;
2136*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_unknown_map_type_modifier);
2137*0b57cec5SDimitry Andric       ConsumeToken();
2138*0b57cec5SDimitry Andric     }
2139*0b57cec5SDimitry Andric     if (getCurToken().is(tok::comma))
2140*0b57cec5SDimitry Andric       ConsumeToken();
2141*0b57cec5SDimitry Andric   }
2142*0b57cec5SDimitry Andric   return false;
2143*0b57cec5SDimitry Andric }
2144*0b57cec5SDimitry Andric 
2145*0b57cec5SDimitry Andric /// Checks if the token is a valid map-type.
2146*0b57cec5SDimitry Andric static OpenMPMapClauseKind isMapType(Parser &P) {
2147*0b57cec5SDimitry Andric   Token Tok = P.getCurToken();
2148*0b57cec5SDimitry Andric   // The map-type token can be either an identifier or the C++ delete keyword.
2149*0b57cec5SDimitry Andric   if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
2150*0b57cec5SDimitry Andric     return OMPC_MAP_unknown;
2151*0b57cec5SDimitry Andric   Preprocessor &PP = P.getPreprocessor();
2152*0b57cec5SDimitry Andric   OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
2153*0b57cec5SDimitry Andric       getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
2154*0b57cec5SDimitry Andric   return MapType;
2155*0b57cec5SDimitry Andric }
2156*0b57cec5SDimitry Andric 
2157*0b57cec5SDimitry Andric /// Parse map-type in map clause.
2158*0b57cec5SDimitry Andric /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
2159*0b57cec5SDimitry Andric /// where, map-type ::= to | from | tofrom | alloc | release | delete
2160*0b57cec5SDimitry Andric static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
2161*0b57cec5SDimitry Andric   Token Tok = P.getCurToken();
2162*0b57cec5SDimitry Andric   if (Tok.is(tok::colon)) {
2163*0b57cec5SDimitry Andric     P.Diag(Tok, diag::err_omp_map_type_missing);
2164*0b57cec5SDimitry Andric     return;
2165*0b57cec5SDimitry Andric   }
2166*0b57cec5SDimitry Andric   Data.MapType = isMapType(P);
2167*0b57cec5SDimitry Andric   if (Data.MapType == OMPC_MAP_unknown)
2168*0b57cec5SDimitry Andric     P.Diag(Tok, diag::err_omp_unknown_map_type);
2169*0b57cec5SDimitry Andric   P.ConsumeToken();
2170*0b57cec5SDimitry Andric }
2171*0b57cec5SDimitry Andric 
2172*0b57cec5SDimitry Andric /// Parses clauses with list.
2173*0b57cec5SDimitry Andric bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
2174*0b57cec5SDimitry Andric                                 OpenMPClauseKind Kind,
2175*0b57cec5SDimitry Andric                                 SmallVectorImpl<Expr *> &Vars,
2176*0b57cec5SDimitry Andric                                 OpenMPVarListDataTy &Data) {
2177*0b57cec5SDimitry Andric   UnqualifiedId UnqualifiedReductionId;
2178*0b57cec5SDimitry Andric   bool InvalidReductionId = false;
2179*0b57cec5SDimitry Andric   bool IsInvalidMapperModifier = false;
2180*0b57cec5SDimitry Andric 
2181*0b57cec5SDimitry Andric   // Parse '('.
2182*0b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2183*0b57cec5SDimitry Andric   if (T.expectAndConsume(diag::err_expected_lparen_after,
2184*0b57cec5SDimitry Andric                          getOpenMPClauseName(Kind)))
2185*0b57cec5SDimitry Andric     return true;
2186*0b57cec5SDimitry Andric 
2187*0b57cec5SDimitry Andric   bool NeedRParenForLinear = false;
2188*0b57cec5SDimitry Andric   BalancedDelimiterTracker LinearT(*this, tok::l_paren,
2189*0b57cec5SDimitry Andric                                   tok::annot_pragma_openmp_end);
2190*0b57cec5SDimitry Andric   // Handle reduction-identifier for reduction clause.
2191*0b57cec5SDimitry Andric   if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
2192*0b57cec5SDimitry Andric       Kind == OMPC_in_reduction) {
2193*0b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
2194*0b57cec5SDimitry Andric     if (getLangOpts().CPlusPlus)
2195*0b57cec5SDimitry Andric       ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
2196*0b57cec5SDimitry Andric                                      /*ObjectType=*/nullptr,
2197*0b57cec5SDimitry Andric                                      /*EnteringContext=*/false);
2198*0b57cec5SDimitry Andric     InvalidReductionId = ParseReductionId(
2199*0b57cec5SDimitry Andric         *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
2200*0b57cec5SDimitry Andric     if (InvalidReductionId) {
2201*0b57cec5SDimitry Andric       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2202*0b57cec5SDimitry Andric                 StopBeforeMatch);
2203*0b57cec5SDimitry Andric     }
2204*0b57cec5SDimitry Andric     if (Tok.is(tok::colon))
2205*0b57cec5SDimitry Andric       Data.ColonLoc = ConsumeToken();
2206*0b57cec5SDimitry Andric     else
2207*0b57cec5SDimitry Andric       Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
2208*0b57cec5SDimitry Andric     if (!InvalidReductionId)
2209*0b57cec5SDimitry Andric       Data.ReductionOrMapperId =
2210*0b57cec5SDimitry Andric           Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
2211*0b57cec5SDimitry Andric   } else if (Kind == OMPC_depend) {
2212*0b57cec5SDimitry Andric   // Handle dependency type for depend clause.
2213*0b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
2214*0b57cec5SDimitry Andric     Data.DepKind =
2215*0b57cec5SDimitry Andric         static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
2216*0b57cec5SDimitry Andric             Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
2217*0b57cec5SDimitry Andric     Data.DepLinMapLoc = Tok.getLocation();
2218*0b57cec5SDimitry Andric 
2219*0b57cec5SDimitry Andric     if (Data.DepKind == OMPC_DEPEND_unknown) {
2220*0b57cec5SDimitry Andric       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2221*0b57cec5SDimitry Andric                 StopBeforeMatch);
2222*0b57cec5SDimitry Andric     } else {
2223*0b57cec5SDimitry Andric       ConsumeToken();
2224*0b57cec5SDimitry Andric       // Special processing for depend(source) clause.
2225*0b57cec5SDimitry Andric       if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
2226*0b57cec5SDimitry Andric         // Parse ')'.
2227*0b57cec5SDimitry Andric         T.consumeClose();
2228*0b57cec5SDimitry Andric         return false;
2229*0b57cec5SDimitry Andric       }
2230*0b57cec5SDimitry Andric     }
2231*0b57cec5SDimitry Andric     if (Tok.is(tok::colon)) {
2232*0b57cec5SDimitry Andric       Data.ColonLoc = ConsumeToken();
2233*0b57cec5SDimitry Andric     } else {
2234*0b57cec5SDimitry Andric       Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
2235*0b57cec5SDimitry Andric                                       : diag::warn_pragma_expected_colon)
2236*0b57cec5SDimitry Andric           << "dependency type";
2237*0b57cec5SDimitry Andric     }
2238*0b57cec5SDimitry Andric   } else if (Kind == OMPC_linear) {
2239*0b57cec5SDimitry Andric     // Try to parse modifier if any.
2240*0b57cec5SDimitry Andric     if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
2241*0b57cec5SDimitry Andric       Data.LinKind = static_cast<OpenMPLinearClauseKind>(
2242*0b57cec5SDimitry Andric           getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2243*0b57cec5SDimitry Andric       Data.DepLinMapLoc = ConsumeToken();
2244*0b57cec5SDimitry Andric       LinearT.consumeOpen();
2245*0b57cec5SDimitry Andric       NeedRParenForLinear = true;
2246*0b57cec5SDimitry Andric     }
2247*0b57cec5SDimitry Andric   } else if (Kind == OMPC_map) {
2248*0b57cec5SDimitry Andric     // Handle map type for map clause.
2249*0b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
2250*0b57cec5SDimitry Andric 
2251*0b57cec5SDimitry Andric     // The first identifier may be a list item, a map-type or a
2252*0b57cec5SDimitry Andric     // map-type-modifier. The map-type can also be delete which has the same
2253*0b57cec5SDimitry Andric     // spelling of the C++ delete keyword.
2254*0b57cec5SDimitry Andric     Data.DepLinMapLoc = Tok.getLocation();
2255*0b57cec5SDimitry Andric 
2256*0b57cec5SDimitry Andric     // Check for presence of a colon in the map clause.
2257*0b57cec5SDimitry Andric     TentativeParsingAction TPA(*this);
2258*0b57cec5SDimitry Andric     bool ColonPresent = false;
2259*0b57cec5SDimitry Andric     if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2260*0b57cec5SDimitry Andric         StopBeforeMatch)) {
2261*0b57cec5SDimitry Andric       if (Tok.is(tok::colon))
2262*0b57cec5SDimitry Andric         ColonPresent = true;
2263*0b57cec5SDimitry Andric     }
2264*0b57cec5SDimitry Andric     TPA.Revert();
2265*0b57cec5SDimitry Andric     // Only parse map-type-modifier[s] and map-type if a colon is present in
2266*0b57cec5SDimitry Andric     // the map clause.
2267*0b57cec5SDimitry Andric     if (ColonPresent) {
2268*0b57cec5SDimitry Andric       IsInvalidMapperModifier = parseMapTypeModifiers(Data);
2269*0b57cec5SDimitry Andric       if (!IsInvalidMapperModifier)
2270*0b57cec5SDimitry Andric         parseMapType(*this, Data);
2271*0b57cec5SDimitry Andric       else
2272*0b57cec5SDimitry Andric         SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
2273*0b57cec5SDimitry Andric     }
2274*0b57cec5SDimitry Andric     if (Data.MapType == OMPC_MAP_unknown) {
2275*0b57cec5SDimitry Andric       Data.MapType = OMPC_MAP_tofrom;
2276*0b57cec5SDimitry Andric       Data.IsMapTypeImplicit = true;
2277*0b57cec5SDimitry Andric     }
2278*0b57cec5SDimitry Andric 
2279*0b57cec5SDimitry Andric     if (Tok.is(tok::colon))
2280*0b57cec5SDimitry Andric       Data.ColonLoc = ConsumeToken();
2281*0b57cec5SDimitry Andric   } else if (Kind == OMPC_to || Kind == OMPC_from) {
2282*0b57cec5SDimitry Andric     if (Tok.is(tok::identifier)) {
2283*0b57cec5SDimitry Andric       bool IsMapperModifier = false;
2284*0b57cec5SDimitry Andric       if (Kind == OMPC_to) {
2285*0b57cec5SDimitry Andric         auto Modifier = static_cast<OpenMPToModifierKind>(
2286*0b57cec5SDimitry Andric             getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2287*0b57cec5SDimitry Andric         if (Modifier == OMPC_TO_MODIFIER_mapper)
2288*0b57cec5SDimitry Andric           IsMapperModifier = true;
2289*0b57cec5SDimitry Andric       } else {
2290*0b57cec5SDimitry Andric         auto Modifier = static_cast<OpenMPFromModifierKind>(
2291*0b57cec5SDimitry Andric             getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
2292*0b57cec5SDimitry Andric         if (Modifier == OMPC_FROM_MODIFIER_mapper)
2293*0b57cec5SDimitry Andric           IsMapperModifier = true;
2294*0b57cec5SDimitry Andric       }
2295*0b57cec5SDimitry Andric       if (IsMapperModifier) {
2296*0b57cec5SDimitry Andric         // Parse the mapper modifier.
2297*0b57cec5SDimitry Andric         ConsumeToken();
2298*0b57cec5SDimitry Andric         IsInvalidMapperModifier = parseMapperModifier(Data);
2299*0b57cec5SDimitry Andric         if (Tok.isNot(tok::colon)) {
2300*0b57cec5SDimitry Andric           if (!IsInvalidMapperModifier)
2301*0b57cec5SDimitry Andric             Diag(Tok, diag::warn_pragma_expected_colon) << ")";
2302*0b57cec5SDimitry Andric           SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2303*0b57cec5SDimitry Andric                     StopBeforeMatch);
2304*0b57cec5SDimitry Andric         }
2305*0b57cec5SDimitry Andric         // Consume ':'.
2306*0b57cec5SDimitry Andric         if (Tok.is(tok::colon))
2307*0b57cec5SDimitry Andric           ConsumeToken();
2308*0b57cec5SDimitry Andric       }
2309*0b57cec5SDimitry Andric     }
2310*0b57cec5SDimitry Andric   } else if (Kind == OMPC_allocate) {
2311*0b57cec5SDimitry Andric     // Handle optional allocator expression followed by colon delimiter.
2312*0b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this);
2313*0b57cec5SDimitry Andric     TentativeParsingAction TPA(*this);
2314*0b57cec5SDimitry Andric     ExprResult Tail =
2315*0b57cec5SDimitry Andric         Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2316*0b57cec5SDimitry Andric     Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
2317*0b57cec5SDimitry Andric                                        /*DiscardedValue=*/false);
2318*0b57cec5SDimitry Andric     if (Tail.isUsable()) {
2319*0b57cec5SDimitry Andric       if (Tok.is(tok::colon)) {
2320*0b57cec5SDimitry Andric         Data.TailExpr = Tail.get();
2321*0b57cec5SDimitry Andric         Data.ColonLoc = ConsumeToken();
2322*0b57cec5SDimitry Andric         TPA.Commit();
2323*0b57cec5SDimitry Andric       } else {
2324*0b57cec5SDimitry Andric         // colon not found, no allocator specified, parse only list of
2325*0b57cec5SDimitry Andric         // variables.
2326*0b57cec5SDimitry Andric         TPA.Revert();
2327*0b57cec5SDimitry Andric       }
2328*0b57cec5SDimitry Andric     } else {
2329*0b57cec5SDimitry Andric       // Parsing was unsuccessfull, revert and skip to the end of clause or
2330*0b57cec5SDimitry Andric       // directive.
2331*0b57cec5SDimitry Andric       TPA.Revert();
2332*0b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2333*0b57cec5SDimitry Andric                 StopBeforeMatch);
2334*0b57cec5SDimitry Andric     }
2335*0b57cec5SDimitry Andric   }
2336*0b57cec5SDimitry Andric 
2337*0b57cec5SDimitry Andric   bool IsComma =
2338*0b57cec5SDimitry Andric       (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
2339*0b57cec5SDimitry Andric        Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
2340*0b57cec5SDimitry Andric       (Kind == OMPC_reduction && !InvalidReductionId) ||
2341*0b57cec5SDimitry Andric       (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) ||
2342*0b57cec5SDimitry Andric       (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
2343*0b57cec5SDimitry Andric   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
2344*0b57cec5SDimitry Andric   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
2345*0b57cec5SDimitry Andric                      Tok.isNot(tok::annot_pragma_openmp_end))) {
2346*0b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
2347*0b57cec5SDimitry Andric     // Parse variable
2348*0b57cec5SDimitry Andric     ExprResult VarExpr =
2349*0b57cec5SDimitry Andric         Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2350*0b57cec5SDimitry Andric     if (VarExpr.isUsable()) {
2351*0b57cec5SDimitry Andric       Vars.push_back(VarExpr.get());
2352*0b57cec5SDimitry Andric     } else {
2353*0b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2354*0b57cec5SDimitry Andric                 StopBeforeMatch);
2355*0b57cec5SDimitry Andric     }
2356*0b57cec5SDimitry Andric     // Skip ',' if any
2357*0b57cec5SDimitry Andric     IsComma = Tok.is(tok::comma);
2358*0b57cec5SDimitry Andric     if (IsComma)
2359*0b57cec5SDimitry Andric       ConsumeToken();
2360*0b57cec5SDimitry Andric     else if (Tok.isNot(tok::r_paren) &&
2361*0b57cec5SDimitry Andric              Tok.isNot(tok::annot_pragma_openmp_end) &&
2362*0b57cec5SDimitry Andric              (!MayHaveTail || Tok.isNot(tok::colon)))
2363*0b57cec5SDimitry Andric       Diag(Tok, diag::err_omp_expected_punc)
2364*0b57cec5SDimitry Andric           << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
2365*0b57cec5SDimitry Andric                                    : getOpenMPClauseName(Kind))
2366*0b57cec5SDimitry Andric           << (Kind == OMPC_flush);
2367*0b57cec5SDimitry Andric   }
2368*0b57cec5SDimitry Andric 
2369*0b57cec5SDimitry Andric   // Parse ')' for linear clause with modifier.
2370*0b57cec5SDimitry Andric   if (NeedRParenForLinear)
2371*0b57cec5SDimitry Andric     LinearT.consumeClose();
2372*0b57cec5SDimitry Andric 
2373*0b57cec5SDimitry Andric   // Parse ':' linear-step (or ':' alignment).
2374*0b57cec5SDimitry Andric   const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
2375*0b57cec5SDimitry Andric   if (MustHaveTail) {
2376*0b57cec5SDimitry Andric     Data.ColonLoc = Tok.getLocation();
2377*0b57cec5SDimitry Andric     SourceLocation ELoc = ConsumeToken();
2378*0b57cec5SDimitry Andric     ExprResult Tail = ParseAssignmentExpression();
2379*0b57cec5SDimitry Andric     Tail =
2380*0b57cec5SDimitry Andric         Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
2381*0b57cec5SDimitry Andric     if (Tail.isUsable())
2382*0b57cec5SDimitry Andric       Data.TailExpr = Tail.get();
2383*0b57cec5SDimitry Andric     else
2384*0b57cec5SDimitry Andric       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2385*0b57cec5SDimitry Andric                 StopBeforeMatch);
2386*0b57cec5SDimitry Andric   }
2387*0b57cec5SDimitry Andric 
2388*0b57cec5SDimitry Andric   // Parse ')'.
2389*0b57cec5SDimitry Andric   Data.RLoc = Tok.getLocation();
2390*0b57cec5SDimitry Andric   if (!T.consumeClose())
2391*0b57cec5SDimitry Andric     Data.RLoc = T.getCloseLocation();
2392*0b57cec5SDimitry Andric   return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
2393*0b57cec5SDimitry Andric           Vars.empty()) ||
2394*0b57cec5SDimitry Andric          (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
2395*0b57cec5SDimitry Andric          (MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
2396*0b57cec5SDimitry Andric          IsInvalidMapperModifier;
2397*0b57cec5SDimitry Andric }
2398*0b57cec5SDimitry Andric 
2399*0b57cec5SDimitry Andric /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
2400*0b57cec5SDimitry Andric /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
2401*0b57cec5SDimitry Andric /// 'in_reduction'.
2402*0b57cec5SDimitry Andric ///
2403*0b57cec5SDimitry Andric ///    private-clause:
2404*0b57cec5SDimitry Andric ///       'private' '(' list ')'
2405*0b57cec5SDimitry Andric ///    firstprivate-clause:
2406*0b57cec5SDimitry Andric ///       'firstprivate' '(' list ')'
2407*0b57cec5SDimitry Andric ///    lastprivate-clause:
2408*0b57cec5SDimitry Andric ///       'lastprivate' '(' list ')'
2409*0b57cec5SDimitry Andric ///    shared-clause:
2410*0b57cec5SDimitry Andric ///       'shared' '(' list ')'
2411*0b57cec5SDimitry Andric ///    linear-clause:
2412*0b57cec5SDimitry Andric ///       'linear' '(' linear-list [ ':' linear-step ] ')'
2413*0b57cec5SDimitry Andric ///    aligned-clause:
2414*0b57cec5SDimitry Andric ///       'aligned' '(' list [ ':' alignment ] ')'
2415*0b57cec5SDimitry Andric ///    reduction-clause:
2416*0b57cec5SDimitry Andric ///       'reduction' '(' reduction-identifier ':' list ')'
2417*0b57cec5SDimitry Andric ///    task_reduction-clause:
2418*0b57cec5SDimitry Andric ///       'task_reduction' '(' reduction-identifier ':' list ')'
2419*0b57cec5SDimitry Andric ///    in_reduction-clause:
2420*0b57cec5SDimitry Andric ///       'in_reduction' '(' reduction-identifier ':' list ')'
2421*0b57cec5SDimitry Andric ///    copyprivate-clause:
2422*0b57cec5SDimitry Andric ///       'copyprivate' '(' list ')'
2423*0b57cec5SDimitry Andric ///    flush-clause:
2424*0b57cec5SDimitry Andric ///       'flush' '(' list ')'
2425*0b57cec5SDimitry Andric ///    depend-clause:
2426*0b57cec5SDimitry Andric ///       'depend' '(' in | out | inout : list | source ')'
2427*0b57cec5SDimitry Andric ///    map-clause:
2428*0b57cec5SDimitry Andric ///       'map' '(' [ [ always [,] ] [ close [,] ]
2429*0b57cec5SDimitry Andric ///          [ mapper '(' mapper-identifier ')' [,] ]
2430*0b57cec5SDimitry Andric ///          to | from | tofrom | alloc | release | delete ':' ] list ')';
2431*0b57cec5SDimitry Andric ///    to-clause:
2432*0b57cec5SDimitry Andric ///       'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2433*0b57cec5SDimitry Andric ///    from-clause:
2434*0b57cec5SDimitry Andric ///       'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
2435*0b57cec5SDimitry Andric ///    use_device_ptr-clause:
2436*0b57cec5SDimitry Andric ///       'use_device_ptr' '(' list ')'
2437*0b57cec5SDimitry Andric ///    is_device_ptr-clause:
2438*0b57cec5SDimitry Andric ///       'is_device_ptr' '(' list ')'
2439*0b57cec5SDimitry Andric ///    allocate-clause:
2440*0b57cec5SDimitry Andric ///       'allocate' '(' [ allocator ':' ] list ')'
2441*0b57cec5SDimitry Andric ///
2442*0b57cec5SDimitry Andric /// For 'linear' clause linear-list may have the following forms:
2443*0b57cec5SDimitry Andric ///  list
2444*0b57cec5SDimitry Andric ///  modifier(list)
2445*0b57cec5SDimitry Andric /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
2446*0b57cec5SDimitry Andric OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
2447*0b57cec5SDimitry Andric                                             OpenMPClauseKind Kind,
2448*0b57cec5SDimitry Andric                                             bool ParseOnly) {
2449*0b57cec5SDimitry Andric   SourceLocation Loc = Tok.getLocation();
2450*0b57cec5SDimitry Andric   SourceLocation LOpen = ConsumeToken();
2451*0b57cec5SDimitry Andric   SmallVector<Expr *, 4> Vars;
2452*0b57cec5SDimitry Andric   OpenMPVarListDataTy Data;
2453*0b57cec5SDimitry Andric 
2454*0b57cec5SDimitry Andric   if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
2455*0b57cec5SDimitry Andric     return nullptr;
2456*0b57cec5SDimitry Andric 
2457*0b57cec5SDimitry Andric   if (ParseOnly)
2458*0b57cec5SDimitry Andric     return nullptr;
2459*0b57cec5SDimitry Andric   OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
2460*0b57cec5SDimitry Andric   return Actions.ActOnOpenMPVarListClause(
2461*0b57cec5SDimitry Andric       Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
2462*0b57cec5SDimitry Andric       Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.DepKind,
2463*0b57cec5SDimitry Andric       Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
2464*0b57cec5SDimitry Andric       Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc);
2465*0b57cec5SDimitry Andric }
2466*0b57cec5SDimitry Andric 
2467