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