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