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