Bug Summary

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