Bug Summary

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