Coverage Report

Created: 2024-01-17 10:31

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