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