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