Bug Summary

File:build/llvm-toolchain-snapshot-16~++20221003111214+1fa2019828ca/clang/lib/Parse/ParseOpenMP.cpp
Warning:line 2841, column 7
Value stored to 'HasImplicitClause' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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