llvm-project

Форк
0
/
ParseOpenMP.cpp 
4929 строк · 180.3 Кб
1
//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// \file
9
/// This file implements parsing of all OpenMP directives and clauses.
10
///
11
//===----------------------------------------------------------------------===//
12

13
#include "clang/AST/ASTContext.h"
14
#include "clang/AST/OpenMPClause.h"
15
#include "clang/AST/StmtOpenMP.h"
16
#include "clang/Basic/OpenMPKinds.h"
17
#include "clang/Basic/TargetInfo.h"
18
#include "clang/Basic/TokenKinds.h"
19
#include "clang/Parse/ParseDiagnostic.h"
20
#include "clang/Parse/Parser.h"
21
#include "clang/Parse/RAIIObjectsForParser.h"
22
#include "clang/Sema/EnterExpressionEvaluationContext.h"
23
#include "clang/Sema/Scope.h"
24
#include "clang/Sema/SemaAMDGPU.h"
25
#include "clang/Sema/SemaCodeCompletion.h"
26
#include "clang/Sema/SemaOpenMP.h"
27
#include "llvm/ADT/SmallBitVector.h"
28
#include "llvm/ADT/StringSwitch.h"
29
#include "llvm/Frontend/OpenMP/OMPAssume.h"
30
#include "llvm/Frontend/OpenMP/OMPContext.h"
31
#include <optional>
32

33
using namespace clang;
34
using namespace llvm::omp;
35

36
//===----------------------------------------------------------------------===//
37
// OpenMP declarative directives.
38
//===----------------------------------------------------------------------===//
39

40
namespace {
41
enum OpenMPDirectiveKindEx {
42
  OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
43
  OMPD_data,
44
  OMPD_declare,
45
  OMPD_end,
46
  OMPD_end_declare,
47
  OMPD_enter,
48
  OMPD_exit,
49
  OMPD_point,
50
  OMPD_reduction,
51
  OMPD_target_enter,
52
  OMPD_target_exit,
53
  OMPD_update,
54
  OMPD_distribute_parallel,
55
  OMPD_teams_distribute_parallel,
56
  OMPD_target_teams_distribute_parallel,
57
  OMPD_mapper,
58
  OMPD_variant,
59
  OMPD_begin,
60
  OMPD_begin_declare,
61
};
62

63
// Helper to unify the enum class OpenMPDirectiveKind with its extension
64
// the OpenMPDirectiveKindEx enum which allows to use them together as if they
65
// are unsigned values.
66
struct OpenMPDirectiveKindExWrapper {
67
  OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
68
  OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
69
  bool operator==(OpenMPDirectiveKindExWrapper V) const {
70
    return Value == V.Value;
71
  }
72
  bool operator!=(OpenMPDirectiveKindExWrapper V) const {
73
    return Value != V.Value;
74
  }
75
  bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
76
  bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
77
  bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
78
  operator unsigned() const { return Value; }
79
  operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
80
  unsigned Value;
81
};
82

83
class DeclDirectiveListParserHelper final {
84
  SmallVector<Expr *, 4> Identifiers;
85
  Parser *P;
86
  OpenMPDirectiveKind Kind;
87

88
public:
89
  DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
90
      : P(P), Kind(Kind) {}
91
  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
92
    ExprResult Res = P->getActions().OpenMP().ActOnOpenMPIdExpression(
93
        P->getCurScope(), SS, NameInfo, Kind);
94
    if (Res.isUsable())
95
      Identifiers.push_back(Res.get());
96
  }
97
  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
98
};
99
} // namespace
100

101
// Map token string to extended OMP token kind that are
102
// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
103
static unsigned getOpenMPDirectiveKindEx(StringRef S) {
104
  OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
105
  if (DKind != OMPD_unknown)
106
    return DKind;
107

108
  return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
109
      .Case("cancellation", OMPD_cancellation)
110
      .Case("data", OMPD_data)
111
      .Case("declare", OMPD_declare)
112
      .Case("end", OMPD_end)
113
      .Case("enter", OMPD_enter)
114
      .Case("exit", OMPD_exit)
115
      .Case("point", OMPD_point)
116
      .Case("reduction", OMPD_reduction)
117
      .Case("update", OMPD_update)
118
      .Case("mapper", OMPD_mapper)
119
      .Case("variant", OMPD_variant)
120
      .Case("begin", OMPD_begin)
121
      .Default(OMPD_unknown);
122
}
123

124
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
125
  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
126
  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
127
  // TODO: add other combined directives in topological order.
128
  static const OpenMPDirectiveKindExWrapper F[][3] = {
129
      {OMPD_begin, OMPD_declare, OMPD_begin_declare},
130
      {OMPD_begin, OMPD_assumes, OMPD_begin_assumes},
131
      {OMPD_end, OMPD_declare, OMPD_end_declare},
132
      {OMPD_end, OMPD_assumes, OMPD_end_assumes},
133
      {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
134
      {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
135
      {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
136
      {OMPD_declare, OMPD_simd, OMPD_declare_simd},
137
      {OMPD_declare, OMPD_target, OMPD_declare_target},
138
      {OMPD_declare, OMPD_variant, OMPD_declare_variant},
139
      {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
140
      {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
141
      {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
142
      {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
143
      {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
144
      {OMPD_distribute_parallel_for, OMPD_simd,
145
       OMPD_distribute_parallel_for_simd},
146
      {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
147
      {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
148
      {OMPD_target, OMPD_data, OMPD_target_data},
149
      {OMPD_target, OMPD_enter, OMPD_target_enter},
150
      {OMPD_target, OMPD_exit, OMPD_target_exit},
151
      {OMPD_target, OMPD_update, OMPD_target_update},
152
      {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
153
      {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
154
      {OMPD_for, OMPD_simd, OMPD_for_simd},
155
      {OMPD_parallel, OMPD_for, OMPD_parallel_for},
156
      {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
157
      {OMPD_parallel, OMPD_loop, OMPD_parallel_loop},
158
      {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
159
      {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
160
      {OMPD_target, OMPD_parallel, OMPD_target_parallel},
161
      {OMPD_target, OMPD_simd, OMPD_target_simd},
162
      {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},
163
      {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
164
      {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
165
      {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
166
      {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
167
      {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
168
      {OMPD_teams_distribute_parallel, OMPD_for,
169
       OMPD_teams_distribute_parallel_for},
170
      {OMPD_teams_distribute_parallel_for, OMPD_simd,
171
       OMPD_teams_distribute_parallel_for_simd},
172
      {OMPD_teams, OMPD_loop, OMPD_teams_loop},
173
      {OMPD_target, OMPD_teams, OMPD_target_teams},
174
      {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
175
      {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},
176
      {OMPD_target_teams_distribute, OMPD_parallel,
177
       OMPD_target_teams_distribute_parallel},
178
      {OMPD_target_teams_distribute, OMPD_simd,
179
       OMPD_target_teams_distribute_simd},
180
      {OMPD_target_teams_distribute_parallel, OMPD_for,
181
       OMPD_target_teams_distribute_parallel_for},
182
      {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
183
       OMPD_target_teams_distribute_parallel_for_simd},
184
      {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
185
      {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},
186
      {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
187
      {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},
188
      {OMPD_parallel, OMPD_master, OMPD_parallel_master},
189
      {OMPD_parallel, OMPD_masked, OMPD_parallel_masked},
190
      {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
191
      {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},
192
      {OMPD_parallel_master_taskloop, OMPD_simd,
193
       OMPD_parallel_master_taskloop_simd},
194
      {OMPD_parallel_masked_taskloop, OMPD_simd,
195
       OMPD_parallel_masked_taskloop_simd}};
196
  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
197
  Token Tok = P.getCurToken();
198
  OpenMPDirectiveKindExWrapper DKind =
199
      Tok.isAnnotation()
200
          ? static_cast<unsigned>(OMPD_unknown)
201
          : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
202
  if (DKind == OMPD_unknown)
203
    return OMPD_unknown;
204

205
  for (const auto &I : F) {
206
    if (DKind != I[0])
207
      continue;
208

209
    Tok = P.getPreprocessor().LookAhead(0);
210
    OpenMPDirectiveKindExWrapper SDKind =
211
        Tok.isAnnotation()
212
            ? static_cast<unsigned>(OMPD_unknown)
213
            : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
214
    if (SDKind == OMPD_unknown)
215
      continue;
216

217
    if (SDKind == I[1]) {
218
      P.ConsumeToken();
219
      DKind = I[2];
220
    }
221
  }
222
  return unsigned(DKind) < llvm::omp::Directive_enumSize
223
             ? static_cast<OpenMPDirectiveKind>(DKind)
224
             : OMPD_unknown;
225
}
226

227
static DeclarationName parseOpenMPReductionId(Parser &P) {
228
  Token Tok = P.getCurToken();
229
  Sema &Actions = P.getActions();
230
  OverloadedOperatorKind OOK = OO_None;
231
  // Allow to use 'operator' keyword for C++ operators
232
  bool WithOperator = false;
233
  if (Tok.is(tok::kw_operator)) {
234
    P.ConsumeToken();
235
    Tok = P.getCurToken();
236
    WithOperator = true;
237
  }
238
  switch (Tok.getKind()) {
239
  case tok::plus: // '+'
240
    OOK = OO_Plus;
241
    break;
242
  case tok::minus: // '-'
243
    OOK = OO_Minus;
244
    break;
245
  case tok::star: // '*'
246
    OOK = OO_Star;
247
    break;
248
  case tok::amp: // '&'
249
    OOK = OO_Amp;
250
    break;
251
  case tok::pipe: // '|'
252
    OOK = OO_Pipe;
253
    break;
254
  case tok::caret: // '^'
255
    OOK = OO_Caret;
256
    break;
257
  case tok::ampamp: // '&&'
258
    OOK = OO_AmpAmp;
259
    break;
260
  case tok::pipepipe: // '||'
261
    OOK = OO_PipePipe;
262
    break;
263
  case tok::identifier: // identifier
264
    if (!WithOperator)
265
      break;
266
    [[fallthrough]];
267
  default:
268
    P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
269
    P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
270
                Parser::StopBeforeMatch);
271
    return DeclarationName();
272
  }
273
  P.ConsumeToken();
274
  auto &DeclNames = Actions.getASTContext().DeclarationNames;
275
  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
276
                        : DeclNames.getCXXOperatorName(OOK);
277
}
278

279
/// Parse 'omp declare reduction' construct.
280
///
281
///       declare-reduction-directive:
282
///        annot_pragma_openmp 'declare' 'reduction'
283
///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
284
///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
285
///        annot_pragma_openmp_end
286
/// <reduction_id> is either a base language identifier or one of the following
287
/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
288
///
289
Parser::DeclGroupPtrTy
290
Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
291
  // Parse '('.
292
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
293
  if (T.expectAndConsume(
294
          diag::err_expected_lparen_after,
295
          getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
296
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
297
    return DeclGroupPtrTy();
298
  }
299

300
  DeclarationName Name = parseOpenMPReductionId(*this);
301
  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
302
    return DeclGroupPtrTy();
303

304
  // Consume ':'.
305
  bool IsCorrect = !ExpectAndConsume(tok::colon);
306

307
  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
308
    return DeclGroupPtrTy();
309

310
  IsCorrect = IsCorrect && !Name.isEmpty();
311

312
  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
313
    Diag(Tok.getLocation(), diag::err_expected_type);
314
    IsCorrect = false;
315
  }
316

317
  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
318
    return DeclGroupPtrTy();
319

320
  SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
321
  // Parse list of types until ':' token.
322
  do {
323
    ColonProtectionRAIIObject ColonRAII(*this);
324
    SourceRange Range;
325
    TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS);
326
    if (TR.isUsable()) {
327
      QualType ReductionType = Actions.OpenMP().ActOnOpenMPDeclareReductionType(
328
          Range.getBegin(), TR);
329
      if (!ReductionType.isNull()) {
330
        ReductionTypes.push_back(
331
            std::make_pair(ReductionType, Range.getBegin()));
332
      }
333
    } else {
334
      SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
335
                StopBeforeMatch);
336
    }
337

338
    if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
339
      break;
340

341
    // Consume ','.
342
    if (ExpectAndConsume(tok::comma)) {
343
      IsCorrect = false;
344
      if (Tok.is(tok::annot_pragma_openmp_end)) {
345
        Diag(Tok.getLocation(), diag::err_expected_type);
346
        return DeclGroupPtrTy();
347
      }
348
    }
349
  } while (Tok.isNot(tok::annot_pragma_openmp_end));
350

351
  if (ReductionTypes.empty()) {
352
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
353
    return DeclGroupPtrTy();
354
  }
355

356
  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
357
    return DeclGroupPtrTy();
358

359
  // Consume ':'.
360
  if (ExpectAndConsume(tok::colon))
361
    IsCorrect = false;
362

363
  if (Tok.is(tok::annot_pragma_openmp_end)) {
364
    Diag(Tok.getLocation(), diag::err_expected_expression);
365
    return DeclGroupPtrTy();
366
  }
367

368
  DeclGroupPtrTy DRD =
369
      Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveStart(
370
          getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes,
371
          AS);
372

373
  // Parse <combiner> expression and then parse initializer if any for each
374
  // correct type.
375
  unsigned I = 0, E = ReductionTypes.size();
376
  for (Decl *D : DRD.get()) {
377
    TentativeParsingAction TPA(*this);
378
    ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
379
                                    Scope::CompoundStmtScope |
380
                                    Scope::OpenMPDirectiveScope);
381
    // Parse <combiner> expression.
382
    Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
383
    ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
384
        ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
385
    Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerEnd(
386
        D, CombinerResult.get());
387

388
    if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
389
        Tok.isNot(tok::annot_pragma_openmp_end)) {
390
      TPA.Commit();
391
      IsCorrect = false;
392
      break;
393
    }
394
    IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
395
    ExprResult InitializerResult;
396
    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
397
      // Parse <initializer> expression.
398
      if (Tok.is(tok::identifier) &&
399
          Tok.getIdentifierInfo()->isStr("initializer")) {
400
        ConsumeToken();
401
      } else {
402
        Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
403
        TPA.Commit();
404
        IsCorrect = false;
405
        break;
406
      }
407
      // Parse '('.
408
      BalancedDelimiterTracker T(*this, tok::l_paren,
409
                                 tok::annot_pragma_openmp_end);
410
      IsCorrect =
411
          !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
412
          IsCorrect;
413
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
414
        ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
415
                                        Scope::CompoundStmtScope |
416
                                        Scope::OpenMPDirectiveScope);
417
        // Parse expression.
418
        VarDecl *OmpPrivParm =
419
            Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerStart(
420
                getCurScope(), D);
421
        // Check if initializer is omp_priv <init_expr> or something else.
422
        if (Tok.is(tok::identifier) &&
423
            Tok.getIdentifierInfo()->isStr("omp_priv")) {
424
          ConsumeToken();
425
          ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
426
        } else {
427
          InitializerResult = Actions.ActOnFinishFullExpr(
428
              ParseAssignmentExpression().get(), D->getLocation(),
429
              /*DiscardedValue*/ false);
430
        }
431
        Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerEnd(
432
            D, InitializerResult.get(), OmpPrivParm);
433
        if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
434
            Tok.isNot(tok::annot_pragma_openmp_end)) {
435
          TPA.Commit();
436
          IsCorrect = false;
437
          break;
438
        }
439
        IsCorrect =
440
            !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
441
      }
442
    }
443

444
    ++I;
445
    // Revert parsing if not the last type, otherwise accept it, we're done with
446
    // parsing.
447
    if (I != E)
448
      TPA.Revert();
449
    else
450
      TPA.Commit();
451
  }
452
  return Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveEnd(
453
      getCurScope(), DRD, IsCorrect);
454
}
455

456
void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
457
  // Parse declarator '=' initializer.
458
  // If a '==' or '+=' is found, suggest a fixit to '='.
459
  if (isTokenEqualOrEqualTypo()) {
460
    ConsumeToken();
461

462
    if (Tok.is(tok::code_completion)) {
463
      cutOffParsing();
464
      Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),
465
                                                       OmpPrivParm);
466
      Actions.FinalizeDeclaration(OmpPrivParm);
467
      return;
468
    }
469

470
    PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
471
    ExprResult Init = ParseInitializer();
472

473
    if (Init.isInvalid()) {
474
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
475
      Actions.ActOnInitializerError(OmpPrivParm);
476
    } else {
477
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
478
                                   /*DirectInit=*/false);
479
    }
480
  } else if (Tok.is(tok::l_paren)) {
481
    // Parse C++ direct initializer: '(' expression-list ')'
482
    BalancedDelimiterTracker T(*this, tok::l_paren);
483
    T.consumeOpen();
484

485
    ExprVector Exprs;
486

487
    SourceLocation LParLoc = T.getOpenLocation();
488
    auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
489
      QualType PreferredType =
490
          Actions.CodeCompletion().ProduceConstructorSignatureHelp(
491
              OmpPrivParm->getType()->getCanonicalTypeInternal(),
492
              OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false);
493
      CalledSignatureHelp = true;
494
      return PreferredType;
495
    };
496
    if (ParseExpressionList(Exprs, [&] {
497
          PreferredType.enterFunctionArgument(Tok.getLocation(),
498
                                              RunSignatureHelp);
499
        })) {
500
      if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
501
        RunSignatureHelp();
502
      Actions.ActOnInitializerError(OmpPrivParm);
503
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
504
    } else {
505
      // Match the ')'.
506
      SourceLocation RLoc = Tok.getLocation();
507
      if (!T.consumeClose())
508
        RLoc = T.getCloseLocation();
509

510
      ExprResult Initializer =
511
          Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
512
      Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
513
                                   /*DirectInit=*/true);
514
    }
515
  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
516
    // Parse C++0x braced-init-list.
517
    Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
518

519
    ExprResult Init(ParseBraceInitializer());
520

521
    if (Init.isInvalid()) {
522
      Actions.ActOnInitializerError(OmpPrivParm);
523
    } else {
524
      Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
525
                                   /*DirectInit=*/true);
526
    }
527
  } else {
528
    Actions.ActOnUninitializedDecl(OmpPrivParm);
529
  }
530
}
531

532
/// Parses 'omp declare mapper' directive.
533
///
534
///       declare-mapper-directive:
535
///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
536
///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
537
///         annot_pragma_openmp_end
538
/// <mapper-identifier> and <var> are base language identifiers.
539
///
540
Parser::DeclGroupPtrTy
541
Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
542
  bool IsCorrect = true;
543
  // Parse '('
544
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
545
  if (T.expectAndConsume(diag::err_expected_lparen_after,
546
                         getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
547
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
548
    return DeclGroupPtrTy();
549
  }
550

551
  // Parse <mapper-identifier>
552
  auto &DeclNames = Actions.getASTContext().DeclarationNames;
553
  DeclarationName MapperId;
554
  if (PP.LookAhead(0).is(tok::colon)) {
555
    if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
556
      Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
557
      IsCorrect = false;
558
    } else {
559
      MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
560
    }
561
    ConsumeToken();
562
    // Consume ':'.
563
    ExpectAndConsume(tok::colon);
564
  } else {
565
    // If no mapper identifier is provided, its name is "default" by default
566
    MapperId =
567
        DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
568
  }
569

570
  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
571
    return DeclGroupPtrTy();
572

573
  // Parse <type> <var>
574
  DeclarationName VName;
575
  QualType MapperType;
576
  SourceRange Range;
577
  TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
578
  if (ParsedType.isUsable())
579
    MapperType = Actions.OpenMP().ActOnOpenMPDeclareMapperType(Range.getBegin(),
580
                                                               ParsedType);
581
  if (MapperType.isNull())
582
    IsCorrect = false;
583
  if (!IsCorrect) {
584
    SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
585
    return DeclGroupPtrTy();
586
  }
587

588
  // Consume ')'.
589
  IsCorrect &= !T.consumeClose();
590
  if (!IsCorrect) {
591
    SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
592
    return DeclGroupPtrTy();
593
  }
594

595
  // Enter scope.
596
  DeclarationNameInfo DirName;
597
  SourceLocation Loc = Tok.getLocation();
598
  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
599
                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
600
  ParseScope OMPDirectiveScope(this, ScopeFlags);
601
  Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName,
602
                                       getCurScope(), Loc);
603

604
  // Add the mapper variable declaration.
605
  ExprResult MapperVarRef =
606
      Actions.OpenMP().ActOnOpenMPDeclareMapperDirectiveVarDecl(
607
          getCurScope(), MapperType, Range.getBegin(), VName);
608

609
  // Parse map clauses.
610
  SmallVector<OMPClause *, 6> Clauses;
611
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
612
    OpenMPClauseKind CKind = Tok.isAnnotation()
613
                                 ? OMPC_unknown
614
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
615
    Actions.OpenMP().StartOpenMPClause(CKind);
616
    OMPClause *Clause =
617
        ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
618
    if (Clause)
619
      Clauses.push_back(Clause);
620
    else
621
      IsCorrect = false;
622
    // Skip ',' if any.
623
    if (Tok.is(tok::comma))
624
      ConsumeToken();
625
    Actions.OpenMP().EndOpenMPClause();
626
  }
627
  if (Clauses.empty()) {
628
    Diag(Tok, diag::err_omp_expected_clause)
629
        << getOpenMPDirectiveName(OMPD_declare_mapper);
630
    IsCorrect = false;
631
  }
632

633
  // Exit scope.
634
  Actions.OpenMP().EndOpenMPDSABlock(nullptr);
635
  OMPDirectiveScope.Exit();
636
  DeclGroupPtrTy DG = Actions.OpenMP().ActOnOpenMPDeclareMapperDirective(
637
      getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
638
      Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);
639
  if (!IsCorrect)
640
    return DeclGroupPtrTy();
641

642
  return DG;
643
}
644

645
TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
646
                                                   DeclarationName &Name,
647
                                                   AccessSpecifier AS) {
648
  // Parse the common declaration-specifiers piece.
649
  Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
650
  DeclSpec DS(AttrFactory);
651
  ParseSpecifierQualifierList(DS, AS, DSC);
652

653
  // Parse the declarator.
654
  DeclaratorContext Context = DeclaratorContext::Prototype;
655
  Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);
656
  ParseDeclarator(DeclaratorInfo);
657
  Range = DeclaratorInfo.getSourceRange();
658
  if (DeclaratorInfo.getIdentifier() == nullptr) {
659
    Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
660
    return true;
661
  }
662
  Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
663

664
  return Actions.OpenMP().ActOnOpenMPDeclareMapperVarDecl(getCurScope(),
665
                                                          DeclaratorInfo);
666
}
667

668
namespace {
669
/// RAII that recreates function context for correct parsing of clauses of
670
/// 'declare simd' construct.
671
/// OpenMP, 2.8.2 declare simd Construct
672
/// The expressions appearing in the clauses of this directive are evaluated in
673
/// the scope of the arguments of the function declaration or definition.
674
class FNContextRAII final {
675
  Parser &P;
676
  Sema::CXXThisScopeRAII *ThisScope;
677
  Parser::MultiParseScope Scopes;
678
  bool HasFunScope = false;
679
  FNContextRAII() = delete;
680
  FNContextRAII(const FNContextRAII &) = delete;
681
  FNContextRAII &operator=(const FNContextRAII &) = delete;
682

683
public:
684
  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) {
685
    Decl *D = *Ptr.get().begin();
686
    NamedDecl *ND = dyn_cast<NamedDecl>(D);
687
    RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
688
    Sema &Actions = P.getActions();
689

690
    // Allow 'this' within late-parsed attributes.
691
    ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
692
                                           ND && ND->isCXXInstanceMember());
693

694
    // If the Decl is templatized, add template parameters to scope.
695
    // FIXME: Track CurTemplateDepth?
696
    P.ReenterTemplateScopes(Scopes, D);
697

698
    // If the Decl is on a function, add function parameters to the scope.
699
    if (D->isFunctionOrFunctionTemplate()) {
700
      HasFunScope = true;
701
      Scopes.Enter(Scope::FnScope | Scope::DeclScope |
702
                   Scope::CompoundStmtScope);
703
      Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
704
    }
705
  }
706
  ~FNContextRAII() {
707
    if (HasFunScope)
708
      P.getActions().ActOnExitFunctionContext();
709
    delete ThisScope;
710
  }
711
};
712
} // namespace
713

714
/// Parses clauses for 'declare simd' directive.
715
///    clause:
716
///      'inbranch' | 'notinbranch'
717
///      'simdlen' '(' <expr> ')'
718
///      { 'uniform' '(' <argument_list> ')' }
719
///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
720
///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }
721
static bool parseDeclareSimdClauses(
722
    Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
723
    SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
724
    SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
725
    SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
726
  SourceRange BSRange;
727
  const Token &Tok = P.getCurToken();
728
  bool IsError = false;
729
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
730
    if (Tok.isNot(tok::identifier))
731
      break;
732
    OMPDeclareSimdDeclAttr::BranchStateTy Out;
733
    IdentifierInfo *II = Tok.getIdentifierInfo();
734
    StringRef ClauseName = II->getName();
735
    // Parse 'inranch|notinbranch' clauses.
736
    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
737
      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
738
        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
739
            << ClauseName
740
            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
741
        IsError = true;
742
      }
743
      BS = Out;
744
      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
745
      P.ConsumeToken();
746
    } else if (ClauseName == "simdlen") {
747
      if (SimdLen.isUsable()) {
748
        P.Diag(Tok, diag::err_omp_more_one_clause)
749
            << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
750
        IsError = true;
751
      }
752
      P.ConsumeToken();
753
      SourceLocation RLoc;
754
      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
755
      if (SimdLen.isInvalid())
756
        IsError = true;
757
    } else {
758
      OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
759
      if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
760
          CKind == OMPC_linear) {
761
        SemaOpenMP::OpenMPVarListDataTy Data;
762
        SmallVectorImpl<Expr *> *Vars = &Uniforms;
763
        if (CKind == OMPC_aligned) {
764
          Vars = &Aligneds;
765
        } else if (CKind == OMPC_linear) {
766
          Data.ExtraModifier = OMPC_LINEAR_val;
767
          Vars = &Linears;
768
        }
769

770
        P.ConsumeToken();
771
        if (P.ParseOpenMPVarList(OMPD_declare_simd,
772
                                 getOpenMPClauseKind(ClauseName), *Vars, Data))
773
          IsError = true;
774
        if (CKind == OMPC_aligned) {
775
          Alignments.append(Aligneds.size() - Alignments.size(),
776
                            Data.DepModOrTailExpr);
777
        } else if (CKind == OMPC_linear) {
778
          assert(0 <= Data.ExtraModifier &&
779
                 Data.ExtraModifier <= OMPC_LINEAR_unknown &&
780
                 "Unexpected linear modifier.");
781
          if (P.getActions().OpenMP().CheckOpenMPLinearModifier(
782
                  static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
783
                  Data.ExtraModifierLoc))
784
            Data.ExtraModifier = OMPC_LINEAR_val;
785
          LinModifiers.append(Linears.size() - LinModifiers.size(),
786
                              Data.ExtraModifier);
787
          Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
788
        }
789
      } else
790
        // TODO: add parsing of other clauses.
791
        break;
792
    }
793
    // Skip ',' if any.
794
    if (Tok.is(tok::comma))
795
      P.ConsumeToken();
796
  }
797
  return IsError;
798
}
799

800
/// Parse clauses for '#pragma omp declare simd'.
801
Parser::DeclGroupPtrTy
802
Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
803
                                   CachedTokens &Toks, SourceLocation Loc) {
804
  PP.EnterToken(Tok, /*IsReinject*/ true);
805
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
806
                      /*IsReinject*/ true);
807
  // Consume the previously pushed token.
808
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
809
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
810

811
  FNContextRAII FnContext(*this, Ptr);
812
  OMPDeclareSimdDeclAttr::BranchStateTy BS =
813
      OMPDeclareSimdDeclAttr::BS_Undefined;
814
  ExprResult Simdlen;
815
  SmallVector<Expr *, 4> Uniforms;
816
  SmallVector<Expr *, 4> Aligneds;
817
  SmallVector<Expr *, 4> Alignments;
818
  SmallVector<Expr *, 4> Linears;
819
  SmallVector<unsigned, 4> LinModifiers;
820
  SmallVector<Expr *, 4> Steps;
821
  bool IsError =
822
      parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
823
                              Alignments, Linears, LinModifiers, Steps);
824
  skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
825
  // Skip the last annot_pragma_openmp_end.
826
  SourceLocation EndLoc = ConsumeAnnotationToken();
827
  if (IsError)
828
    return Ptr;
829
  return Actions.OpenMP().ActOnOpenMPDeclareSimdDirective(
830
      Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
831
      LinModifiers, Steps, SourceRange(Loc, EndLoc));
832
}
833

834
namespace {
835
/// Constant used in the diagnostics to distinguish the levels in an OpenMP
836
/// contexts: selector-set={selector(trait, ...), ...}, ....
837
enum OMPContextLvl {
838
  CONTEXT_SELECTOR_SET_LVL = 0,
839
  CONTEXT_SELECTOR_LVL = 1,
840
  CONTEXT_TRAIT_LVL = 2,
841
};
842

843
static StringRef stringLiteralParser(Parser &P) {
844
  ExprResult Res = P.ParseStringLiteralExpression(true);
845
  return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : "";
846
}
847

848
static StringRef getNameFromIdOrString(Parser &P, Token &Tok,
849
                                       OMPContextLvl Lvl) {
850
  if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {
851
    llvm::SmallString<16> Buffer;
852
    StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);
853
    (void)P.ConsumeToken();
854
    return Name;
855
  }
856

857
  if (tok::isStringLiteral(Tok.getKind()))
858
    return stringLiteralParser(P);
859

860
  P.Diag(Tok.getLocation(),
861
         diag::warn_omp_declare_variant_string_literal_or_identifier)
862
      << Lvl;
863
  return "";
864
}
865

866
static bool checkForDuplicates(Parser &P, StringRef Name,
867
                               SourceLocation NameLoc,
868
                               llvm::StringMap<SourceLocation> &Seen,
869
                               OMPContextLvl Lvl) {
870
  auto Res = Seen.try_emplace(Name, NameLoc);
871
  if (Res.second)
872
    return false;
873

874
  // Each trait-set-selector-name, trait-selector-name and trait-name can
875
  // only be specified once.
876
  P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
877
      << Lvl << Name;
878
  P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
879
      << Lvl << Name;
880
  return true;
881
}
882
} // namespace
883

884
void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,
885
                                       llvm::omp::TraitSet Set,
886
                                       llvm::omp::TraitSelector Selector,
887
                                       llvm::StringMap<SourceLocation> &Seen) {
888
  TIProperty.Kind = TraitProperty::invalid;
889

890
  SourceLocation NameLoc = Tok.getLocation();
891
  StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);
892
  if (Name.empty()) {
893
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
894
        << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
895
    return;
896
  }
897

898
  TIProperty.RawString = Name;
899
  TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);
900
  if (TIProperty.Kind != TraitProperty::invalid) {
901
    if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
902
      TIProperty.Kind = TraitProperty::invalid;
903
    return;
904
  }
905

906
  // It follows diagnosis and helping notes.
907
  // FIXME: We should move the diagnosis string generation into libFrontend.
908
  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
909
      << Name << getOpenMPContextTraitSelectorName(Selector)
910
      << getOpenMPContextTraitSetName(Set);
911

912
  TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
913
  if (SetForName != TraitSet::invalid) {
914
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
915
        << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
916
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
917
        << Name << "<selector-name>"
918
        << "(<property-name>)";
919
    return;
920
  }
921
  TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
922
  if (SelectorForName != TraitSelector::invalid) {
923
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
924
        << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
925
    bool AllowsTraitScore = false;
926
    bool RequiresProperty = false;
927
    isValidTraitSelectorForTraitSet(
928
        SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
929
        AllowsTraitScore, RequiresProperty);
930
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
931
        << getOpenMPContextTraitSetName(
932
               getOpenMPContextTraitSetForSelector(SelectorForName))
933
        << Name << (RequiresProperty ? "(<property-name>)" : "");
934
    return;
935
  }
936
  for (const auto &PotentialSet :
937
       {TraitSet::construct, TraitSet::user, TraitSet::implementation,
938
        TraitSet::device}) {
939
    TraitProperty PropertyForName =
940
        getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);
941
    if (PropertyForName == TraitProperty::invalid)
942
      continue;
943
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
944
        << getOpenMPContextTraitSetName(
945
               getOpenMPContextTraitSetForProperty(PropertyForName))
946
        << getOpenMPContextTraitSelectorName(
947
               getOpenMPContextTraitSelectorForProperty(PropertyForName))
948
        << ("(" + Name + ")").str();
949
    return;
950
  }
951
  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
952
      << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);
953
}
954

955
static bool checkExtensionProperty(Parser &P, SourceLocation Loc,
956
                                   OMPTraitProperty &TIProperty,
957
                                   OMPTraitSelector &TISelector,
958
                                   llvm::StringMap<SourceLocation> &Seen) {
959
  assert(TISelector.Kind ==
960
             llvm::omp::TraitSelector::implementation_extension &&
961
         "Only for extension properties, e.g., "
962
         "`implementation={extension(PROPERTY)}`");
963
  if (TIProperty.Kind == TraitProperty::invalid)
964
    return false;
965

966
  if (TIProperty.Kind ==
967
      TraitProperty::implementation_extension_disable_implicit_base)
968
    return true;
969

970
  if (TIProperty.Kind ==
971
      TraitProperty::implementation_extension_allow_templates)
972
    return true;
973

974
  if (TIProperty.Kind ==
975
      TraitProperty::implementation_extension_bind_to_declaration)
976
    return true;
977

978
  auto IsMatchExtension = [](OMPTraitProperty &TP) {
979
    return (TP.Kind ==
980
                llvm::omp::TraitProperty::implementation_extension_match_all ||
981
            TP.Kind ==
982
                llvm::omp::TraitProperty::implementation_extension_match_any ||
983
            TP.Kind ==
984
                llvm::omp::TraitProperty::implementation_extension_match_none);
985
  };
986

987
  if (IsMatchExtension(TIProperty)) {
988
    for (OMPTraitProperty &SeenProp : TISelector.Properties)
989
      if (IsMatchExtension(SeenProp)) {
990
        P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
991
        StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
992
            SeenProp.Kind, SeenProp.RawString);
993
        SourceLocation SeenLoc = Seen[SeenName];
994
        P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
995
            << CONTEXT_TRAIT_LVL << SeenName;
996
        return false;
997
      }
998
    return true;
999
  }
1000

1001
  llvm_unreachable("Unknown extension property!");
1002
}
1003

1004
void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,
1005
                                     llvm::omp::TraitSet Set,
1006
                                     llvm::StringMap<SourceLocation> &Seen) {
1007
  assert(TISelector.Kind != TraitSelector::user_condition &&
1008
         "User conditions are special properties not handled here!");
1009

1010
  SourceLocation PropertyLoc = Tok.getLocation();
1011
  OMPTraitProperty TIProperty;
1012
  parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);
1013

1014
  if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)
1015
    if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty,
1016
                                TISelector, Seen))
1017
      TIProperty.Kind = TraitProperty::invalid;
1018

1019
  // If we have an invalid property here we already issued a warning.
1020
  if (TIProperty.Kind == TraitProperty::invalid) {
1021
    if (PropertyLoc != Tok.getLocation())
1022
      Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1023
          << CONTEXT_TRAIT_LVL;
1024
    return;
1025
  }
1026

1027
  if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,
1028
                                                 TISelector.Kind, Set)) {
1029

1030
    // If we make it here the property, selector, set, score, condition, ... are
1031
    // all valid (or have been corrected). Thus we can record the property.
1032
    TISelector.Properties.push_back(TIProperty);
1033
    return;
1034
  }
1035

1036
  Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
1037
      << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1038
                                           TIProperty.RawString)
1039
      << getOpenMPContextTraitSelectorName(TISelector.Kind)
1040
      << getOpenMPContextTraitSetName(Set);
1041
  Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1042
      << getOpenMPContextTraitPropertyName(TIProperty.Kind,
1043
                                           TIProperty.RawString)
1044
      << getOpenMPContextTraitSelectorName(
1045
             getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))
1046
      << getOpenMPContextTraitSetName(
1047
             getOpenMPContextTraitSetForProperty(TIProperty.Kind));
1048
  Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1049
      << CONTEXT_TRAIT_LVL;
1050
}
1051

1052
void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,
1053
                                       llvm::omp::TraitSet Set,
1054
                                       llvm::StringMap<SourceLocation> &Seen) {
1055
  TISelector.Kind = TraitSelector::invalid;
1056

1057
  SourceLocation NameLoc = Tok.getLocation();
1058
  StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);
1059
  if (Name.empty()) {
1060
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1061
        << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1062
    return;
1063
  }
1064

1065
  TISelector.Kind = getOpenMPContextTraitSelectorKind(Name);
1066
  if (TISelector.Kind != TraitSelector::invalid) {
1067
    if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1068
      TISelector.Kind = TraitSelector::invalid;
1069
    return;
1070
  }
1071

1072
  // It follows diagnosis and helping notes.
1073
  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1074
      << Name << getOpenMPContextTraitSetName(Set);
1075

1076
  TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1077
  if (SetForName != TraitSet::invalid) {
1078
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1079
        << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1080
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1081
        << Name << "<selector-name>"
1082
        << "<property-name>";
1083
    return;
1084
  }
1085
  for (const auto &PotentialSet :
1086
       {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1087
        TraitSet::device}) {
1088
    TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1089
        PotentialSet, TraitSelector::invalid, Name);
1090
    if (PropertyForName == TraitProperty::invalid)
1091
      continue;
1092
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1093
        << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1094
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1095
        << getOpenMPContextTraitSetName(
1096
               getOpenMPContextTraitSetForProperty(PropertyForName))
1097
        << getOpenMPContextTraitSelectorName(
1098
               getOpenMPContextTraitSelectorForProperty(PropertyForName))
1099
        << ("(" + Name + ")").str();
1100
    return;
1101
  }
1102
  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1103
      << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1104
}
1105

1106
/// Parse optional 'score' '(' <expr> ')' ':'.
1107
static ExprResult parseContextScore(Parser &P) {
1108
  ExprResult ScoreExpr;
1109
  llvm::SmallString<16> Buffer;
1110
  StringRef SelectorName =
1111
      P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
1112
  if (SelectorName != "score")
1113
    return ScoreExpr;
1114
  (void)P.ConsumeToken();
1115
  SourceLocation RLoc;
1116
  ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
1117
  // Parse ':'
1118
  if (P.getCurToken().is(tok::colon))
1119
    (void)P.ConsumeAnyToken();
1120
  else
1121
    P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)
1122
        << "':'"
1123
        << "score expression";
1124
  return ScoreExpr;
1125
}
1126

1127
/// Parses an OpenMP context selector.
1128
///
1129
/// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')']
1130
void Parser::parseOMPContextSelector(
1131
    OMPTraitSelector &TISelector, llvm::omp::TraitSet Set,
1132
    llvm::StringMap<SourceLocation> &SeenSelectors) {
1133
  unsigned short OuterPC = ParenCount;
1134

1135
  // If anything went wrong we issue an error or warning and then skip the rest
1136
  // of the selector. However, commas are ambiguous so we look for the nesting
1137
  // of parentheses here as well.
1138
  auto FinishSelector = [OuterPC, this]() -> void {
1139
    bool Done = false;
1140
    while (!Done) {
1141
      while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1142
                         tok::annot_pragma_openmp_end},
1143
                        StopBeforeMatch))
1144
        ;
1145
      if (Tok.is(tok::r_paren) && OuterPC > ParenCount)
1146
        (void)ConsumeParen();
1147
      if (OuterPC <= ParenCount) {
1148
        Done = true;
1149
        break;
1150
      }
1151
      if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {
1152
        Done = true;
1153
        break;
1154
      }
1155
      (void)ConsumeAnyToken();
1156
    }
1157
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1158
        << CONTEXT_SELECTOR_LVL;
1159
  };
1160

1161
  SourceLocation SelectorLoc = Tok.getLocation();
1162
  parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
1163
  if (TISelector.Kind == TraitSelector::invalid)
1164
    return FinishSelector();
1165

1166
  bool AllowsTraitScore = false;
1167
  bool RequiresProperty = false;
1168
  if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,
1169
                                       RequiresProperty)) {
1170
    Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1171
        << getOpenMPContextTraitSelectorName(TISelector.Kind)
1172
        << getOpenMPContextTraitSetName(Set);
1173
    Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1174
        << getOpenMPContextTraitSelectorName(TISelector.Kind)
1175
        << getOpenMPContextTraitSetName(
1176
               getOpenMPContextTraitSetForSelector(TISelector.Kind))
1177
        << RequiresProperty;
1178
    return FinishSelector();
1179
  }
1180

1181
  if (!RequiresProperty) {
1182
    TISelector.Properties.push_back(
1183
        {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),
1184
         getOpenMPContextTraitSelectorName(TISelector.Kind)});
1185
    return;
1186
  }
1187

1188
  if (!Tok.is(tok::l_paren)) {
1189
    Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1190
        << getOpenMPContextTraitSelectorName(TISelector.Kind)
1191
        << getOpenMPContextTraitSetName(Set);
1192
    return FinishSelector();
1193
  }
1194

1195
  if (TISelector.Kind == TraitSelector::user_condition) {
1196
    SourceLocation RLoc;
1197
    ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc);
1198
    if (!Condition.isUsable())
1199
      return FinishSelector();
1200
    TISelector.ScoreOrCondition = Condition.get();
1201
    TISelector.Properties.push_back(
1202
        {TraitProperty::user_condition_unknown, "<condition>"});
1203
    return;
1204
  }
1205

1206
  BalancedDelimiterTracker BDT(*this, tok::l_paren,
1207
                               tok::annot_pragma_openmp_end);
1208
  // Parse '('.
1209
  (void)BDT.consumeOpen();
1210

1211
  SourceLocation ScoreLoc = Tok.getLocation();
1212
  ExprResult Score = parseContextScore(*this);
1213

1214
  if (!AllowsTraitScore && !Score.isUnset()) {
1215
    if (Score.isUsable()) {
1216
      Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1217
          << getOpenMPContextTraitSelectorName(TISelector.Kind)
1218
          << getOpenMPContextTraitSetName(Set) << Score.get();
1219
    } else {
1220
      Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1221
          << getOpenMPContextTraitSelectorName(TISelector.Kind)
1222
          << getOpenMPContextTraitSetName(Set) << "<invalid>";
1223
    }
1224
    Score = ExprResult();
1225
  }
1226

1227
  if (Score.isUsable())
1228
    TISelector.ScoreOrCondition = Score.get();
1229

1230
  llvm::StringMap<SourceLocation> SeenProperties;
1231
  do {
1232
    parseOMPContextProperty(TISelector, Set, SeenProperties);
1233
  } while (TryConsumeToken(tok::comma));
1234

1235
  // Parse ')'.
1236
  BDT.consumeClose();
1237
}
1238

1239
void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,
1240
                                  llvm::StringMap<SourceLocation> &Seen) {
1241
  TISet.Kind = TraitSet::invalid;
1242

1243
  SourceLocation NameLoc = Tok.getLocation();
1244
  StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);
1245
  if (Name.empty()) {
1246
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)
1247
        << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1248
    return;
1249
  }
1250

1251
  TISet.Kind = getOpenMPContextTraitSetKind(Name);
1252
  if (TISet.Kind != TraitSet::invalid) {
1253
    if (checkForDuplicates(*this, Name, NameLoc, Seen,
1254
                           CONTEXT_SELECTOR_SET_LVL))
1255
      TISet.Kind = TraitSet::invalid;
1256
    return;
1257
  }
1258

1259
  // It follows diagnosis and helping notes.
1260
  Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1261

1262
  TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
1263
  if (SelectorForName != TraitSelector::invalid) {
1264
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1265
        << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1266
    bool AllowsTraitScore = false;
1267
    bool RequiresProperty = false;
1268
    isValidTraitSelectorForTraitSet(
1269
        SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1270
        AllowsTraitScore, RequiresProperty);
1271
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1272
        << getOpenMPContextTraitSetName(
1273
               getOpenMPContextTraitSetForSelector(SelectorForName))
1274
        << Name << (RequiresProperty ? "(<property-name>)" : "");
1275
    return;
1276
  }
1277
  for (const auto &PotentialSet :
1278
       {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1279
        TraitSet::device}) {
1280
    TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1281
        PotentialSet, TraitSelector::invalid, Name);
1282
    if (PropertyForName == TraitProperty::invalid)
1283
      continue;
1284
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1285
        << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1286
    Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1287
        << getOpenMPContextTraitSetName(
1288
               getOpenMPContextTraitSetForProperty(PropertyForName))
1289
        << getOpenMPContextTraitSelectorName(
1290
               getOpenMPContextTraitSelectorForProperty(PropertyForName))
1291
        << ("(" + Name + ")").str();
1292
    return;
1293
  }
1294
  Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1295
      << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1296
}
1297

1298
/// Parses an OpenMP context selector set.
1299
///
1300
/// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}'
1301
void Parser::parseOMPContextSelectorSet(
1302
    OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1303
  auto OuterBC = BraceCount;
1304

1305
  // If anything went wrong we issue an error or warning and then skip the rest
1306
  // of the set. However, commas are ambiguous so we look for the nesting
1307
  // of braces here as well.
1308
  auto FinishSelectorSet = [this, OuterBC]() -> void {
1309
    bool Done = false;
1310
    while (!Done) {
1311
      while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1312
                         tok::annot_pragma_openmp_end},
1313
                        StopBeforeMatch))
1314
        ;
1315
      if (Tok.is(tok::r_brace) && OuterBC > BraceCount)
1316
        (void)ConsumeBrace();
1317
      if (OuterBC <= BraceCount) {
1318
        Done = true;
1319
        break;
1320
      }
1321
      if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {
1322
        Done = true;
1323
        break;
1324
      }
1325
      (void)ConsumeAnyToken();
1326
    }
1327
    Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1328
        << CONTEXT_SELECTOR_SET_LVL;
1329
  };
1330

1331
  parseOMPTraitSetKind(TISet, SeenSets);
1332
  if (TISet.Kind == TraitSet::invalid)
1333
    return FinishSelectorSet();
1334

1335
  // Parse '='.
1336
  if (!TryConsumeToken(tok::equal))
1337
    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1338
        << "="
1339
        << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +
1340
            "\"")
1341
               .str();
1342

1343
  // Parse '{'.
1344
  if (Tok.is(tok::l_brace)) {
1345
    (void)ConsumeBrace();
1346
  } else {
1347
    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1348
        << "{"
1349
        << ("'=' that follows the context set name \"" +
1350
            getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1351
               .str();
1352
  }
1353

1354
  llvm::StringMap<SourceLocation> SeenSelectors;
1355
  do {
1356
    OMPTraitSelector TISelector;
1357
    parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);
1358
    if (TISelector.Kind != TraitSelector::invalid &&
1359
        !TISelector.Properties.empty())
1360
      TISet.Selectors.push_back(TISelector);
1361
  } while (TryConsumeToken(tok::comma));
1362

1363
  // Parse '}'.
1364
  if (Tok.is(tok::r_brace)) {
1365
    (void)ConsumeBrace();
1366
  } else {
1367
    Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)
1368
        << "}"
1369
        << ("context selectors for the context set \"" +
1370
            getOpenMPContextTraitSetName(TISet.Kind) + "\"")
1371
               .str();
1372
  }
1373
}
1374

1375
/// Parse OpenMP context selectors:
1376
///
1377
/// <trait-set-selector> [, <trait-set-selector>]*
1378
bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) {
1379
  llvm::StringMap<SourceLocation> SeenSets;
1380
  do {
1381
    OMPTraitSet TISet;
1382
    parseOMPContextSelectorSet(TISet, SeenSets);
1383
    if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())
1384
      TI.Sets.push_back(TISet);
1385
  } while (TryConsumeToken(tok::comma));
1386

1387
  return false;
1388
}
1389

1390
/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
1391
void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
1392
                                           CachedTokens &Toks,
1393
                                           SourceLocation Loc) {
1394
  PP.EnterToken(Tok, /*IsReinject*/ true);
1395
  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1396
                      /*IsReinject*/ true);
1397
  // Consume the previously pushed token.
1398
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1399
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
1400

1401
  FNContextRAII FnContext(*this, Ptr);
1402
  // Parse function declaration id.
1403
  SourceLocation RLoc;
1404
  // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
1405
  // instead of MemberExprs.
1406
  ExprResult AssociatedFunction;
1407
  {
1408
    // Do not mark function as is used to prevent its emission if this is the
1409
    // only place where it is used.
1410
    EnterExpressionEvaluationContext Unevaluated(
1411
        Actions, Sema::ExpressionEvaluationContext::Unevaluated);
1412
    AssociatedFunction = ParseOpenMPParensExpr(
1413
        getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1414
        /*IsAddressOfOperand=*/true);
1415
  }
1416
  if (!AssociatedFunction.isUsable()) {
1417
    if (!Tok.is(tok::annot_pragma_openmp_end))
1418
      while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1419
        ;
1420
    // Skip the last annot_pragma_openmp_end.
1421
    (void)ConsumeAnnotationToken();
1422
    return;
1423
  }
1424

1425
  OMPTraitInfo *ParentTI =
1426
      Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
1427
  ASTContext &ASTCtx = Actions.getASTContext();
1428
  OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
1429
  SmallVector<Expr *, 6> AdjustNothing;
1430
  SmallVector<Expr *, 6> AdjustNeedDevicePtr;
1431
  SmallVector<OMPInteropInfo, 3> AppendArgs;
1432
  SourceLocation AdjustArgsLoc, AppendArgsLoc;
1433

1434
  // At least one clause is required.
1435
  if (Tok.is(tok::annot_pragma_openmp_end)) {
1436
    Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1437
        << (getLangOpts().OpenMP < 51 ? 0 : 1);
1438
  }
1439

1440
  bool IsError = false;
1441
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1442
    OpenMPClauseKind CKind = Tok.isAnnotation()
1443
                                 ? OMPC_unknown
1444
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
1445
    if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
1446
                                     getLangOpts().OpenMP)) {
1447
      Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1448
          << (getLangOpts().OpenMP < 51 ? 0 : 1);
1449
      IsError = true;
1450
    }
1451
    if (!IsError) {
1452
      switch (CKind) {
1453
      case OMPC_match:
1454
        IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
1455
        break;
1456
      case OMPC_adjust_args: {
1457
        AdjustArgsLoc = Tok.getLocation();
1458
        ConsumeToken();
1459
        SemaOpenMP::OpenMPVarListDataTy Data;
1460
        SmallVector<Expr *> Vars;
1461
        IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
1462
                                     Vars, Data);
1463
        if (!IsError)
1464
          llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
1465
                                 ? AdjustNothing
1466
                                 : AdjustNeedDevicePtr,
1467
                             Vars);
1468
        break;
1469
      }
1470
      case OMPC_append_args:
1471
        if (!AppendArgs.empty()) {
1472
          Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1473
              << getOpenMPDirectiveName(OMPD_declare_variant)
1474
              << getOpenMPClauseName(CKind) << 0;
1475
          IsError = true;
1476
        }
1477
        if (!IsError) {
1478
          AppendArgsLoc = Tok.getLocation();
1479
          ConsumeToken();
1480
          IsError = parseOpenMPAppendArgs(AppendArgs);
1481
        }
1482
        break;
1483
      default:
1484
        llvm_unreachable("Unexpected clause for declare variant.");
1485
      }
1486
    }
1487
    if (IsError) {
1488
      while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1489
        ;
1490
      // Skip the last annot_pragma_openmp_end.
1491
      (void)ConsumeAnnotationToken();
1492
      return;
1493
    }
1494
    // Skip ',' if any.
1495
    if (Tok.is(tok::comma))
1496
      ConsumeToken();
1497
  }
1498

1499
  std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1500
      Actions.OpenMP().checkOpenMPDeclareVariantFunction(
1501
          Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
1502
          SourceRange(Loc, Tok.getLocation()));
1503

1504
  if (DeclVarData && !TI.Sets.empty())
1505
    Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(
1506
        DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
1507
        AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
1508
        SourceRange(Loc, Tok.getLocation()));
1509

1510
  // Skip the last annot_pragma_openmp_end.
1511
  (void)ConsumeAnnotationToken();
1512
}
1513

1514
bool Parser::parseOpenMPAppendArgs(
1515
    SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
1516
  bool HasError = false;
1517
  // Parse '('.
1518
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1519
  if (T.expectAndConsume(diag::err_expected_lparen_after,
1520
                         getOpenMPClauseName(OMPC_append_args).data()))
1521
    return true;
1522

1523
  // Parse the list of append-ops, each is;
1524
  // interop(interop-type[,interop-type]...)
1525
  while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {
1526
    ConsumeToken();
1527
    BalancedDelimiterTracker IT(*this, tok::l_paren,
1528
                                tok::annot_pragma_openmp_end);
1529
    if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
1530
      return true;
1531

1532
    OMPInteropInfo InteropInfo;
1533
    if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1534
      HasError = true;
1535
    else
1536
      InteropInfos.push_back(InteropInfo);
1537

1538
    IT.consumeClose();
1539
    if (Tok.is(tok::comma))
1540
      ConsumeToken();
1541
  }
1542
  if (!HasError && InteropInfos.empty()) {
1543
    HasError = true;
1544
    Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);
1545
    SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1546
              StopBeforeMatch);
1547
  }
1548
  HasError = T.consumeClose() || HasError;
1549
  return HasError;
1550
}
1551

1552
bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
1553
                                               OMPTraitInfo &TI,
1554
                                               OMPTraitInfo *ParentTI) {
1555
  // Parse 'match'.
1556
  OpenMPClauseKind CKind = Tok.isAnnotation()
1557
                               ? OMPC_unknown
1558
                               : getOpenMPClauseKind(PP.getSpelling(Tok));
1559
  if (CKind != OMPC_match) {
1560
    Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1561
        << (getLangOpts().OpenMP < 51 ? 0 : 1);
1562
    return true;
1563
  }
1564
  (void)ConsumeToken();
1565
  // Parse '('.
1566
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1567
  if (T.expectAndConsume(diag::err_expected_lparen_after,
1568
                         getOpenMPClauseName(OMPC_match).data()))
1569
    return true;
1570

1571
  // Parse inner context selectors.
1572
  parseOMPContextSelectors(Loc, TI);
1573

1574
  // Parse ')'
1575
  (void)T.consumeClose();
1576

1577
  if (!ParentTI)
1578
    return false;
1579

1580
  // Merge the parent/outer trait info into the one we just parsed and diagnose
1581
  // problems.
1582
  // TODO: Keep some source location in the TI to provide better diagnostics.
1583
  // TODO: Perform some kind of equivalence check on the condition and score
1584
  //       expressions.
1585
  for (const OMPTraitSet &ParentSet : ParentTI->Sets) {
1586
    bool MergedSet = false;
1587
    for (OMPTraitSet &Set : TI.Sets) {
1588
      if (Set.Kind != ParentSet.Kind)
1589
        continue;
1590
      MergedSet = true;
1591
      for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {
1592
        bool MergedSelector = false;
1593
        for (OMPTraitSelector &Selector : Set.Selectors) {
1594
          if (Selector.Kind != ParentSelector.Kind)
1595
            continue;
1596
          MergedSelector = true;
1597
          for (const OMPTraitProperty &ParentProperty :
1598
               ParentSelector.Properties) {
1599
            bool MergedProperty = false;
1600
            for (OMPTraitProperty &Property : Selector.Properties) {
1601
              // Ignore "equivalent" properties.
1602
              if (Property.Kind != ParentProperty.Kind)
1603
                continue;
1604

1605
              // If the kind is the same but the raw string not, we don't want
1606
              // to skip out on the property.
1607
              MergedProperty |= Property.RawString == ParentProperty.RawString;
1608

1609
              if (Property.RawString == ParentProperty.RawString &&
1610
                  Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition)
1611
                continue;
1612

1613
              if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1614
                Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1615
              } else if (Selector.ScoreOrCondition !=
1616
                         ParentSelector.ScoreOrCondition) {
1617
                Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1618
                    << getOpenMPContextTraitPropertyName(
1619
                           ParentProperty.Kind, ParentProperty.RawString)
1620
                    << getOpenMPContextTraitSelectorName(ParentSelector.Kind)
1621
                    << getOpenMPContextTraitSetName(ParentSet.Kind);
1622
              }
1623
            }
1624
            if (!MergedProperty)
1625
              Selector.Properties.push_back(ParentProperty);
1626
          }
1627
        }
1628
        if (!MergedSelector)
1629
          Set.Selectors.push_back(ParentSelector);
1630
      }
1631
    }
1632
    if (!MergedSet)
1633
      TI.Sets.push_back(ParentSet);
1634
  }
1635

1636
  return false;
1637
}
1638

1639
/// <clause> [clause[ [,] clause] ... ]
1640
///
1641
///  clauses: for error directive
1642
///     'at' '(' compilation | execution ')'
1643
///     'severity' '(' fatal | warning ')'
1644
///     'message' '(' msg-string ')'
1645
/// ....
1646
void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
1647
                                SmallVectorImpl<OMPClause *> &Clauses,
1648
                                SourceLocation Loc) {
1649
  std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
1650
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1651
    OpenMPClauseKind CKind = Tok.isAnnotation()
1652
                                 ? OMPC_unknown
1653
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
1654
    Actions.OpenMP().StartOpenMPClause(CKind);
1655
    OMPClause *Clause =
1656
        ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
1657
    SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1658
              StopBeforeMatch);
1659
    SeenClauses[unsigned(CKind)] = true;
1660
    if (Clause != nullptr)
1661
      Clauses.push_back(Clause);
1662
    if (Tok.is(tok::annot_pragma_openmp_end)) {
1663
      Actions.OpenMP().EndOpenMPClause();
1664
      break;
1665
    }
1666
    // Skip ',' if any.
1667
    if (Tok.is(tok::comma))
1668
      ConsumeToken();
1669
    Actions.OpenMP().EndOpenMPClause();
1670
  }
1671
}
1672

1673
/// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
1674
/// where
1675
///
1676
///   clause:
1677
///     'ext_IMPL_DEFINED'
1678
///     'absent' '(' directive-name [, directive-name]* ')'
1679
///     'contains' '(' directive-name [, directive-name]* ')'
1680
///     'holds' '(' scalar-expression ')'
1681
///     'no_openmp'
1682
///     'no_openmp_routines'
1683
///     'no_parallelism'
1684
///
1685
void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
1686
                                         SourceLocation Loc) {
1687
  SmallVector<std::string, 4> Assumptions;
1688
  bool SkippedClauses = false;
1689

1690
  auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {
1691
    BalancedDelimiterTracker T(*this, tok::l_paren,
1692
                               tok::annot_pragma_openmp_end);
1693
    if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1694
      return;
1695
    T.skipToEnd();
1696
    if (IssueNote && T.getCloseLocation().isValid())
1697
      Diag(T.getCloseLocation(),
1698
           diag::note_omp_assumption_clause_continue_here);
1699
  };
1700

1701
  /// Helper to determine which AssumptionClauseMapping (ACM) in the
1702
  /// AssumptionClauseMappings table matches \p RawString. The return value is
1703
  /// the index of the matching ACM into the table or -1 if there was no match.
1704
  auto MatchACMClause = [&](StringRef RawString) {
1705
    llvm::StringSwitch<int> SS(RawString);
1706
    unsigned ACMIdx = 0;
1707
    for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1708
      if (ACMI.StartsWith)
1709
        SS.StartsWith(ACMI.Identifier, ACMIdx++);
1710
      else
1711
        SS.Case(ACMI.Identifier, ACMIdx++);
1712
    }
1713
    return SS.Default(-1);
1714
  };
1715

1716
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1717
    IdentifierInfo *II = nullptr;
1718
    SourceLocation StartLoc = Tok.getLocation();
1719
    int Idx = -1;
1720
    if (Tok.isAnyIdentifier()) {
1721
      II = Tok.getIdentifierInfo();
1722
      Idx = MatchACMClause(II->getName());
1723
    }
1724
    ConsumeAnyToken();
1725

1726
    bool NextIsLPar = Tok.is(tok::l_paren);
1727
    // Handle unknown clauses by skipping them.
1728
    if (Idx == -1) {
1729
      Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1730
          << llvm::omp::getOpenMPDirectiveName(DKind)
1731
          << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1732
      if (NextIsLPar)
1733
        SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
1734
      SkippedClauses = true;
1735
      continue;
1736
    }
1737
    const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1738
    if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1739
      // TODO: We ignore absent, contains, and holds assumptions for now. We
1740
      //       also do not verify the content in the parenthesis at all.
1741
      SkippedClauses = true;
1742
      SkipBraces(II->getName(), /* IssueNote */ false);
1743
      continue;
1744
    }
1745

1746
    if (NextIsLPar) {
1747
      Diag(Tok.getLocation(),
1748
           diag::warn_omp_unknown_assumption_clause_without_args)
1749
          << II;
1750
      SkipBraces(II->getName(), /* IssueNote */ true);
1751
    }
1752

1753
    assert(II && "Expected an identifier clause!");
1754
    std::string Assumption = II->getName().str();
1755
    if (ACMI.StartsWith)
1756
      Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());
1757
    else
1758
      Assumption = "omp_" + Assumption;
1759
    Assumptions.push_back(Assumption);
1760
  }
1761

1762
  Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,
1763
                                               SkippedClauses);
1764
}
1765

1766
void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {
1767
  if (Actions.OpenMP().isInOpenMPAssumeScope())
1768
    Actions.OpenMP().ActOnOpenMPEndAssumesDirective();
1769
  else
1770
    Diag(Loc, diag::err_expected_begin_assumes);
1771
}
1772

1773
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1774
///
1775
///    default-clause:
1776
///         'default' '(' 'none' | 'shared'  | 'private' | 'firstprivate' ')
1777
///
1778
///    proc_bind-clause:
1779
///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
1780
///
1781
///    device_type-clause:
1782
///         'device_type' '(' 'host' | 'nohost' | 'any' )'
1783
namespace {
1784
struct SimpleClauseData {
1785
  unsigned Type;
1786
  SourceLocation Loc;
1787
  SourceLocation LOpen;
1788
  SourceLocation TypeLoc;
1789
  SourceLocation RLoc;
1790
  SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1791
                   SourceLocation TypeLoc, SourceLocation RLoc)
1792
      : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1793
};
1794
} // anonymous namespace
1795

1796
static std::optional<SimpleClauseData>
1797
parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
1798
  const Token &Tok = P.getCurToken();
1799
  SourceLocation Loc = Tok.getLocation();
1800
  SourceLocation LOpen = P.ConsumeToken();
1801
  // Parse '('.
1802
  BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
1803
  if (T.expectAndConsume(diag::err_expected_lparen_after,
1804
                         getOpenMPClauseName(Kind).data()))
1805
    return std::nullopt;
1806

1807
  unsigned Type = getOpenMPSimpleClauseType(
1808
      Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
1809
      P.getLangOpts());
1810
  SourceLocation TypeLoc = Tok.getLocation();
1811
  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1812
      Tok.isNot(tok::annot_pragma_openmp_end))
1813
    P.ConsumeAnyToken();
1814

1815
  // Parse ')'.
1816
  SourceLocation RLoc = Tok.getLocation();
1817
  if (!T.consumeClose())
1818
    RLoc = T.getCloseLocation();
1819

1820
  return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1821
}
1822

1823
void Parser::ParseOMPDeclareTargetClauses(
1824
    SemaOpenMP::DeclareTargetContextInfo &DTCI) {
1825
  SourceLocation DeviceTypeLoc;
1826
  bool RequiresToOrLinkOrIndirectClause = false;
1827
  bool HasToOrLinkOrIndirectClause = false;
1828
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1829
    OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1830
    bool HasIdentifier = Tok.is(tok::identifier);
1831
    if (HasIdentifier) {
1832
      // If we see any clause we need a to or link clause.
1833
      RequiresToOrLinkOrIndirectClause = true;
1834
      IdentifierInfo *II = Tok.getIdentifierInfo();
1835
      StringRef ClauseName = II->getName();
1836
      bool IsDeviceTypeClause =
1837
          getLangOpts().OpenMP >= 50 &&
1838
          getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1839

1840
      bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
1841
                              getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1842
      if (DTCI.Indirect && IsIndirectClause) {
1843
        Diag(Tok, diag::err_omp_more_one_clause)
1844
            << getOpenMPDirectiveName(OMPD_declare_target)
1845
            << getOpenMPClauseName(OMPC_indirect) << 0;
1846
        break;
1847
      }
1848
      bool IsToEnterOrLinkClause =
1849
          OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1850
      assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
1851
             "Cannot be both!");
1852

1853
      // Starting with OpenMP 5.2 the `to` clause has been replaced by the
1854
      // `enter` clause.
1855
      if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
1856
        Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1857
        break;
1858
      }
1859
      if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
1860
        Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1861
        break;
1862
      }
1863

1864
      if (!IsDeviceTypeClause && !IsIndirectClause &&
1865
          DTCI.Kind == OMPD_begin_declare_target) {
1866
        Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1867
            << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
1868
        break;
1869
      }
1870
      if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
1871
        Diag(Tok, getLangOpts().OpenMP >= 52
1872
                      ? diag::err_omp_declare_target_unexpected_clause_52
1873
                      : diag::err_omp_declare_target_unexpected_clause)
1874
            << ClauseName
1875
            << (getLangOpts().OpenMP >= 51
1876
                    ? 4
1877
                    : getLangOpts().OpenMP >= 50 ? 2 : 1);
1878
        break;
1879
      }
1880

1881
      if (IsToEnterOrLinkClause || IsIndirectClause)
1882
        HasToOrLinkOrIndirectClause = true;
1883

1884
      if (IsIndirectClause) {
1885
        if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
1886
          break;
1887
        continue;
1888
      }
1889
      // Parse 'device_type' clause and go to next clause if any.
1890
      if (IsDeviceTypeClause) {
1891
        std::optional<SimpleClauseData> DevTypeData =
1892
            parseOpenMPSimpleClause(*this, OMPC_device_type);
1893
        if (DevTypeData) {
1894
          if (DeviceTypeLoc.isValid()) {
1895
            // We already saw another device_type clause, diagnose it.
1896
            Diag(DevTypeData->Loc,
1897
                 diag::warn_omp_more_one_device_type_clause);
1898
            break;
1899
          }
1900
          switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
1901
          case OMPC_DEVICE_TYPE_any:
1902
            DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1903
            break;
1904
          case OMPC_DEVICE_TYPE_host:
1905
            DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1906
            break;
1907
          case OMPC_DEVICE_TYPE_nohost:
1908
            DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1909
            break;
1910
          case OMPC_DEVICE_TYPE_unknown:
1911
            llvm_unreachable("Unexpected device_type");
1912
          }
1913
          DeviceTypeLoc = DevTypeData->Loc;
1914
        }
1915
        continue;
1916
      }
1917
      ConsumeToken();
1918
    }
1919

1920
    if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1921
      auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,
1922
                                          DeclarationNameInfo NameInfo) {
1923
        NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(
1924
            getCurScope(), SS, NameInfo);
1925
        if (!ND)
1926
          return;
1927
        SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};
1928
        bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1929
        if (!FirstMapping)
1930
          Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)
1931
              << NameInfo.getName();
1932
      };
1933
      if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1934
                                   /*AllowScopeSpecifier=*/true))
1935
        break;
1936
    }
1937

1938
    if (Tok.is(tok::l_paren)) {
1939
      Diag(Tok,
1940
           diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1941
      break;
1942
    }
1943
    if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
1944
      Diag(Tok,
1945
           getLangOpts().OpenMP >= 52
1946
               ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1947
               : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1948
      break;
1949
    }
1950

1951
    // Consume optional ','.
1952
    if (Tok.is(tok::comma))
1953
      ConsumeToken();
1954
  }
1955

1956
  if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1957
    Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1958

1959
  // For declare target require at least 'to' or 'link' to be present.
1960
  if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
1961
      !HasToOrLinkOrIndirectClause)
1962
    Diag(DTCI.Loc,
1963
         getLangOpts().OpenMP >= 52
1964
             ? diag::err_omp_declare_target_missing_enter_or_link_clause
1965
             : diag::err_omp_declare_target_missing_to_or_link_clause)
1966
        << (getLangOpts().OpenMP >= 51 ? 1 : 0);
1967

1968
  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1969
}
1970

1971
void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) {
1972
  // The last seen token is annot_pragma_openmp_end - need to check for
1973
  // extra tokens.
1974
  if (Tok.is(tok::annot_pragma_openmp_end))
1975
    return;
1976

1977
  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1978
      << getOpenMPDirectiveName(DKind);
1979
  while (Tok.isNot(tok::annot_pragma_openmp_end))
1980
    ConsumeAnyToken();
1981
}
1982

1983
void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind,
1984
                                  OpenMPDirectiveKind ExpectedKind,
1985
                                  OpenMPDirectiveKind FoundKind,
1986
                                  SourceLocation BeginLoc,
1987
                                  SourceLocation FoundLoc,
1988
                                  bool SkipUntilOpenMPEnd) {
1989
  int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1990

1991
  if (FoundKind == ExpectedKind) {
1992
    ConsumeAnyToken();
1993
    skipUntilPragmaOpenMPEnd(ExpectedKind);
1994
    return;
1995
  }
1996

1997
  Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1998
      << DiagSelection;
1999
  Diag(BeginLoc, diag::note_matching)
2000
      << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
2001
  if (SkipUntilOpenMPEnd)
2002
    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
2003
}
2004

2005
void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,
2006
                                               OpenMPDirectiveKind EndDKind,
2007
                                               SourceLocation DKLoc) {
2008
  parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
2009
                       Tok.getLocation(),
2010
                       /* SkipUntilOpenMPEnd */ false);
2011
  // Skip the last annot_pragma_openmp_end.
2012
  if (Tok.is(tok::annot_pragma_openmp_end))
2013
    ConsumeAnnotationToken();
2014
}
2015

2016
/// Parsing of declarative OpenMP directives.
2017
///
2018
///       threadprivate-directive:
2019
///         annot_pragma_openmp 'threadprivate' simple-variable-list
2020
///         annot_pragma_openmp_end
2021
///
2022
///       allocate-directive:
2023
///         annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
2024
///         annot_pragma_openmp_end
2025
///
2026
///       declare-reduction-directive:
2027
///        annot_pragma_openmp 'declare' 'reduction' [...]
2028
///        annot_pragma_openmp_end
2029
///
2030
///       declare-mapper-directive:
2031
///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
2032
///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
2033
///         annot_pragma_openmp_end
2034
///
2035
///       declare-simd-directive:
2036
///         annot_pragma_openmp 'declare simd' {<clause> [,]}
2037
///         annot_pragma_openmp_end
2038
///         <function declaration/definition>
2039
///
2040
///       requires directive:
2041
///         annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
2042
///         annot_pragma_openmp_end
2043
///
2044
///       assumes directive:
2045
///         annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ]
2046
///         annot_pragma_openmp_end
2047
///       or
2048
///         annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ]
2049
///         annot_pragma_openmp 'end assumes'
2050
///         annot_pragma_openmp_end
2051
///
2052
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
2053
    AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed,
2054
    DeclSpec::TST TagType, Decl *Tag) {
2055
  assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2056
         "Not an OpenMP directive!");
2057
  ParsingOpenMPDirectiveRAII DirScope(*this);
2058
  ParenBraceBracketBalancer BalancerRAIIObj(*this);
2059

2060
  SourceLocation Loc;
2061
  OpenMPDirectiveKind DKind;
2062
  if (Delayed) {
2063
    TentativeParsingAction TPA(*this);
2064
    Loc = ConsumeAnnotationToken();
2065
    DKind = parseOpenMPDirectiveKind(*this);
2066
    if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
2067
      // Need to delay parsing until completion of the parent class.
2068
      TPA.Revert();
2069
      CachedTokens Toks;
2070
      unsigned Cnt = 1;
2071
      Toks.push_back(Tok);
2072
      while (Cnt && Tok.isNot(tok::eof)) {
2073
        (void)ConsumeAnyToken();
2074
        if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
2075
          ++Cnt;
2076
        else if (Tok.is(tok::annot_pragma_openmp_end))
2077
          --Cnt;
2078
        Toks.push_back(Tok);
2079
      }
2080
      // Skip last annot_pragma_openmp_end.
2081
      if (Cnt == 0)
2082
        (void)ConsumeAnyToken();
2083
      auto *LP = new LateParsedPragma(this, AS);
2084
      LP->takeToks(Toks);
2085
      getCurrentClass().LateParsedDeclarations.push_back(LP);
2086
      return nullptr;
2087
    }
2088
    TPA.Commit();
2089
  } else {
2090
    Loc = ConsumeAnnotationToken();
2091
    DKind = parseOpenMPDirectiveKind(*this);
2092
  }
2093

2094
  switch (DKind) {
2095
  case OMPD_threadprivate: {
2096
    ConsumeToken();
2097
    DeclDirectiveListParserHelper Helper(this, DKind);
2098
    if (!ParseOpenMPSimpleVarList(DKind, Helper,
2099
                                  /*AllowScopeSpecifier=*/true)) {
2100
      skipUntilPragmaOpenMPEnd(DKind);
2101
      // Skip the last annot_pragma_openmp_end.
2102
      ConsumeAnnotationToken();
2103
      return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2104
          Loc, Helper.getIdentifiers());
2105
    }
2106
    break;
2107
  }
2108
  case OMPD_allocate: {
2109
    ConsumeToken();
2110
    DeclDirectiveListParserHelper Helper(this, DKind);
2111
    if (!ParseOpenMPSimpleVarList(DKind, Helper,
2112
                                  /*AllowScopeSpecifier=*/true)) {
2113
      SmallVector<OMPClause *, 1> Clauses;
2114
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2115
        std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;
2116
        while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2117
          OpenMPClauseKind CKind =
2118
              Tok.isAnnotation() ? OMPC_unknown
2119
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
2120
          Actions.OpenMP().StartOpenMPClause(CKind);
2121
          OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2122
                                                !SeenClauses[unsigned(CKind)]);
2123
          SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2124
                    StopBeforeMatch);
2125
          SeenClauses[unsigned(CKind)] = true;
2126
          if (Clause != nullptr)
2127
            Clauses.push_back(Clause);
2128
          if (Tok.is(tok::annot_pragma_openmp_end)) {
2129
            Actions.OpenMP().EndOpenMPClause();
2130
            break;
2131
          }
2132
          // Skip ',' if any.
2133
          if (Tok.is(tok::comma))
2134
            ConsumeToken();
2135
          Actions.OpenMP().EndOpenMPClause();
2136
        }
2137
        skipUntilPragmaOpenMPEnd(DKind);
2138
      }
2139
      // Skip the last annot_pragma_openmp_end.
2140
      ConsumeAnnotationToken();
2141
      return Actions.OpenMP().ActOnOpenMPAllocateDirective(
2142
          Loc, Helper.getIdentifiers(), Clauses);
2143
    }
2144
    break;
2145
  }
2146
  case OMPD_requires: {
2147
    SourceLocation StartLoc = ConsumeToken();
2148
    SmallVector<OMPClause *, 5> Clauses;
2149
    llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2150
    if (Tok.is(tok::annot_pragma_openmp_end)) {
2151
      Diag(Tok, diag::err_omp_expected_clause)
2152
          << getOpenMPDirectiveName(OMPD_requires);
2153
      break;
2154
    }
2155
    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2156
      OpenMPClauseKind CKind = Tok.isAnnotation()
2157
                                   ? OMPC_unknown
2158
                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
2159
      Actions.OpenMP().StartOpenMPClause(CKind);
2160
      OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
2161
                                            !SeenClauses[unsigned(CKind)]);
2162
      SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2163
                StopBeforeMatch);
2164
      SeenClauses[unsigned(CKind)] = true;
2165
      if (Clause != nullptr)
2166
        Clauses.push_back(Clause);
2167
      if (Tok.is(tok::annot_pragma_openmp_end)) {
2168
        Actions.OpenMP().EndOpenMPClause();
2169
        break;
2170
      }
2171
      // Skip ',' if any.
2172
      if (Tok.is(tok::comma))
2173
        ConsumeToken();
2174
      Actions.OpenMP().EndOpenMPClause();
2175
    }
2176
    // Consume final annot_pragma_openmp_end
2177
    if (Clauses.empty()) {
2178
      Diag(Tok, diag::err_omp_expected_clause)
2179
          << getOpenMPDirectiveName(OMPD_requires);
2180
      ConsumeAnnotationToken();
2181
      return nullptr;
2182
    }
2183
    ConsumeAnnotationToken();
2184
    return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);
2185
  }
2186
  case OMPD_error: {
2187
    SmallVector<OMPClause *, 1> Clauses;
2188
    SourceLocation StartLoc = ConsumeToken();
2189
    ParseOpenMPClauses(DKind, Clauses, StartLoc);
2190
    Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,
2191
                                               SourceLocation(),
2192
                                               /*InExContext = */ false);
2193
    break;
2194
  }
2195
  case OMPD_assumes:
2196
  case OMPD_begin_assumes:
2197
    ParseOpenMPAssumesDirective(DKind, ConsumeToken());
2198
    break;
2199
  case OMPD_end_assumes:
2200
    ParseOpenMPEndAssumesDirective(ConsumeToken());
2201
    break;
2202
  case OMPD_declare_reduction:
2203
    ConsumeToken();
2204
    if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2205
      skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2206
      // Skip the last annot_pragma_openmp_end.
2207
      ConsumeAnnotationToken();
2208
      return Res;
2209
    }
2210
    break;
2211
  case OMPD_declare_mapper: {
2212
    ConsumeToken();
2213
    if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2214
      // Skip the last annot_pragma_openmp_end.
2215
      ConsumeAnnotationToken();
2216
      return Res;
2217
    }
2218
    break;
2219
  }
2220
  case OMPD_begin_declare_variant: {
2221
    // The syntax is:
2222
    // { #pragma omp begin declare variant clause }
2223
    // <function-declaration-or-definition-sequence>
2224
    // { #pragma omp end declare variant }
2225
    //
2226
    ConsumeToken();
2227
    OMPTraitInfo *ParentTI =
2228
        Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
2229
    ASTContext &ASTCtx = Actions.getASTContext();
2230
    OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
2231
    if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
2232
      while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
2233
        ;
2234
      // Skip the last annot_pragma_openmp_end.
2235
      (void)ConsumeAnnotationToken();
2236
      break;
2237
    }
2238

2239
    // Skip last tokens.
2240
    skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
2241

2242
    ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2243

2244
    VariantMatchInfo VMI;
2245
    TI.getAsVariantMatchInfo(ASTCtx, VMI);
2246

2247
    std::function<void(StringRef)> DiagUnknownTrait =
2248
        [this, Loc](StringRef ISATrait) {
2249
          // TODO Track the selector locations in a way that is accessible here
2250
          // to improve the diagnostic location.
2251
          Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2252
        };
2253
    TargetOMPContext OMPCtx(
2254
        ASTCtx, std::move(DiagUnknownTrait),
2255
        /* CurrentFunctionDecl */ nullptr,
2256
        /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>());
2257

2258
    if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) {
2259
      Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);
2260
      break;
2261
    }
2262

2263
    // Elide all the code till the matching end declare variant was found.
2264
    unsigned Nesting = 1;
2265
    SourceLocation DKLoc;
2266
    OpenMPDirectiveKind DK = OMPD_unknown;
2267
    do {
2268
      DKLoc = Tok.getLocation();
2269
      DK = parseOpenMPDirectiveKind(*this);
2270
      if (DK == OMPD_end_declare_variant)
2271
        --Nesting;
2272
      else if (DK == OMPD_begin_declare_variant)
2273
        ++Nesting;
2274
      if (!Nesting || isEofOrEom())
2275
        break;
2276
      ConsumeAnyToken();
2277
    } while (true);
2278

2279
    parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
2280
                         DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
2281
    if (isEofOrEom())
2282
      return nullptr;
2283
    break;
2284
  }
2285
  case OMPD_end_declare_variant: {
2286
    if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
2287
      Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
2288
    else
2289
      Diag(Loc, diag::err_expected_begin_declare_variant);
2290
    ConsumeToken();
2291
    break;
2292
  }
2293
  case OMPD_declare_variant:
2294
  case OMPD_declare_simd: {
2295
    // The syntax is:
2296
    // { #pragma omp declare {simd|variant} }
2297
    // <function-declaration-or-definition>
2298
    //
2299
    CachedTokens Toks;
2300
    Toks.push_back(Tok);
2301
    ConsumeToken();
2302
    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2303
      Toks.push_back(Tok);
2304
      ConsumeAnyToken();
2305
    }
2306
    Toks.push_back(Tok);
2307
    ConsumeAnyToken();
2308

2309
    DeclGroupPtrTy Ptr;
2310
    if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2311
      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2312
                                                       TagType, Tag);
2313
    } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
2314
      // Here we expect to see some function declaration.
2315
      if (AS == AS_none) {
2316
        assert(TagType == DeclSpec::TST_unspecified);
2317
        ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2318
        MaybeParseCXX11Attributes(Attrs);
2319
        ParsingDeclSpec PDS(*this);
2320
        Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2321
      } else {
2322
        Ptr =
2323
            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
2324
      }
2325
    }
2326
    if (!Ptr) {
2327
      Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2328
          << (DKind == OMPD_declare_simd ? 0 : 1);
2329
      return DeclGroupPtrTy();
2330
    }
2331
    if (DKind == OMPD_declare_simd)
2332
      return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2333
    assert(DKind == OMPD_declare_variant &&
2334
           "Expected declare variant directive only");
2335
    ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2336
    return Ptr;
2337
  }
2338
  case OMPD_begin_declare_target:
2339
  case OMPD_declare_target: {
2340
    SourceLocation DTLoc = ConsumeAnyToken();
2341
    bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2342
    SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2343
    if (HasClauses)
2344
      ParseOMPDeclareTargetClauses(DTCI);
2345
    bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2346
                               !HasClauses ||
2347
                               (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2348

2349
    // Skip the last annot_pragma_openmp_end.
2350
    ConsumeAnyToken();
2351

2352
    if (HasImplicitMappings) {
2353
      Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);
2354
      return nullptr;
2355
    }
2356

2357
    Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2358
    llvm::SmallVector<Decl *, 4> Decls;
2359
    for (auto &It : DTCI.ExplicitlyMapped)
2360
      Decls.push_back(It.first);
2361
    return Actions.BuildDeclaratorGroup(Decls);
2362
  }
2363
  case OMPD_end_declare_target: {
2364
    if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
2365
      Diag(Tok, diag::err_omp_unexpected_directive)
2366
          << 1 << getOpenMPDirectiveName(DKind);
2367
      break;
2368
    }
2369
    const SemaOpenMP::DeclareTargetContextInfo &DTCI =
2370
        Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();
2371
    ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2372
    return nullptr;
2373
  }
2374
  case OMPD_unknown:
2375
    Diag(Tok, diag::err_omp_unknown_directive);
2376
    break;
2377
  default:
2378
    switch (getDirectiveCategory(DKind)) {
2379
    case Category::Executable:
2380
    case Category::Meta:
2381
    case Category::Subsidiary:
2382
    case Category::Utility:
2383
      Diag(Tok, diag::err_omp_unexpected_directive)
2384
          << 1 << getOpenMPDirectiveName(DKind);
2385
      break;
2386
    case Category::Declarative:
2387
    case Category::Informational:
2388
      break;
2389
    }
2390
  }
2391
  while (Tok.isNot(tok::annot_pragma_openmp_end))
2392
    ConsumeAnyToken();
2393
  ConsumeAnyToken();
2394
  return nullptr;
2395
}
2396

2397
StmtResult Parser::ParseOpenMPExecutableDirective(
2398
    ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2399
    bool ReadDirectiveWithinMetadirective) {
2400
  assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2401

2402
  bool HasAssociatedStatement = true;
2403
  Association Assoc = getDirectiveAssociation(DKind);
2404

2405
  // OMPD_ordered has None as association, but it comes in two variants,
2406
  // the second of which is associated with a block.
2407
  // OMPD_scan and OMPD_section are both "separating", but section is treated
2408
  // as if it was associated with a statement, while scan is not.
2409
  if (DKind != OMPD_ordered && DKind != OMPD_section &&
2410
      (Assoc == Association::None || Assoc == Association::Separating)) {
2411
    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2412
        ParsedStmtContext()) {
2413
      Diag(Tok, diag::err_omp_immediate_directive)
2414
          << getOpenMPDirectiveName(DKind) << 0;
2415
      if (DKind == OMPD_error) {
2416
        SkipUntil(tok::annot_pragma_openmp_end);
2417
        return StmtError();
2418
      }
2419
    }
2420
    HasAssociatedStatement = false;
2421
  }
2422

2423
  SourceLocation EndLoc;
2424
  SmallVector<OMPClause *, 5> Clauses;
2425
  llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2426
  DeclarationNameInfo DirName;
2427
  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2428
  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2429
                        Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
2430

2431
  // Special processing for flush and depobj clauses.
2432
  Token ImplicitTok;
2433
  bool ImplicitClauseAllowed = false;
2434
  if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2435
    ImplicitTok = Tok;
2436
    ImplicitClauseAllowed = true;
2437
  }
2438
  ConsumeToken();
2439
  // Parse directive name of the 'critical' directive if any.
2440
  if (DKind == OMPD_critical) {
2441
    BalancedDelimiterTracker T(*this, tok::l_paren,
2442
                               tok::annot_pragma_openmp_end);
2443
    if (!T.consumeOpen()) {
2444
      if (Tok.isAnyIdentifier()) {
2445
        DirName =
2446
            DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
2447
        ConsumeAnyToken();
2448
      } else {
2449
        Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2450
      }
2451
      T.consumeClose();
2452
    }
2453
  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2454
    CancelRegion = parseOpenMPDirectiveKind(*this);
2455
    if (Tok.isNot(tok::annot_pragma_openmp_end))
2456
      ConsumeToken();
2457
  }
2458

2459
  if (isOpenMPLoopDirective(DKind))
2460
    ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2461
  if (isOpenMPSimdDirective(DKind))
2462
    ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2463
  ParseScope OMPDirectiveScope(this, ScopeFlags);
2464
  Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2465
                                       Loc);
2466

2467
  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2468
    // If we are parsing for a directive within a metadirective, the directive
2469
    // ends with a ')'.
2470
    if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2471
      while (Tok.isNot(tok::annot_pragma_openmp_end))
2472
        ConsumeAnyToken();
2473
      break;
2474
    }
2475
    bool HasImplicitClause = false;
2476
    if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2477
      HasImplicitClause = true;
2478
      // Push copy of the current token back to stream to properly parse
2479
      // pseudo-clause OMPFlushClause or OMPDepobjClause.
2480
      PP.EnterToken(Tok, /*IsReinject*/ true);
2481
      PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2482
      ConsumeAnyToken();
2483
    }
2484
    OpenMPClauseKind CKind = Tok.isAnnotation()
2485
                                 ? OMPC_unknown
2486
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
2487
    if (HasImplicitClause) {
2488
      assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2489
      if (DKind == OMPD_flush) {
2490
        CKind = OMPC_flush;
2491
      } else {
2492
        assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2493
        CKind = OMPC_depobj;
2494
      }
2495
    }
2496
    // No more implicit clauses allowed.
2497
    ImplicitClauseAllowed = false;
2498
    Actions.OpenMP().StartOpenMPClause(CKind);
2499
    HasImplicitClause = false;
2500
    OMPClause *Clause =
2501
        ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2502
    SeenClauses[unsigned(CKind)] = true;
2503
    if (Clause)
2504
      Clauses.push_back(Clause);
2505

2506
    // Skip ',' if any.
2507
    if (Tok.is(tok::comma))
2508
      ConsumeToken();
2509
    Actions.OpenMP().EndOpenMPClause();
2510
  }
2511
  // End location of the directive.
2512
  EndLoc = Tok.getLocation();
2513
  // Consume final annot_pragma_openmp_end.
2514
  ConsumeAnnotationToken();
2515

2516
  if (DKind == OMPD_ordered) {
2517
    // If the depend or doacross clause is specified, the ordered construct
2518
    // is a stand-alone directive.
2519
    for (auto CK : {OMPC_depend, OMPC_doacross}) {
2520
      if (SeenClauses[unsigned(CK)]) {
2521
        if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2522
            ParsedStmtContext()) {
2523
          Diag(Loc, diag::err_omp_immediate_directive)
2524
              << getOpenMPDirectiveName(DKind) << 1 << getOpenMPClauseName(CK);
2525
        }
2526
        HasAssociatedStatement = false;
2527
      }
2528
    }
2529
  }
2530

2531
  if (DKind == OMPD_tile && !SeenClauses[unsigned(OMPC_sizes)]) {
2532
    Diag(Loc, diag::err_omp_required_clause)
2533
        << getOpenMPDirectiveName(OMPD_tile) << "sizes";
2534
  }
2535

2536
  StmtResult AssociatedStmt;
2537
  if (HasAssociatedStatement) {
2538
    // The body is a block scope like in Lambdas and Blocks.
2539
    Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2540
    // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2541
    // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2542
    // should have at least one compound statement scope within it.
2543
    ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2544
    {
2545
      Sema::CompoundScopeRAII Scope(Actions);
2546
      AssociatedStmt = ParseStatement();
2547

2548
      if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2549
          getLangOpts().OpenMPIRBuilder)
2550
        AssociatedStmt =
2551
            Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
2552
    }
2553
    AssociatedStmt =
2554
        Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2555
  } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2556
             DKind == OMPD_target_exit_data) {
2557
    Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2558
    AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2559
                      Actions.ActOnCompoundStmt(Loc, Loc, std::nullopt,
2560
                                                /*isStmtExpr=*/false));
2561
    AssociatedStmt =
2562
        Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2563
  }
2564

2565
  StmtResult Directive = Actions.OpenMP().ActOnOpenMPExecutableDirective(
2566
      DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2567

2568
  // Exit scope.
2569
  Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2570
  OMPDirectiveScope.Exit();
2571

2572
  return Directive;
2573
}
2574

2575
/// Parsing of declarative or executable OpenMP directives.
2576
///
2577
///       threadprivate-directive:
2578
///         annot_pragma_openmp 'threadprivate' simple-variable-list
2579
///         annot_pragma_openmp_end
2580
///
2581
///       allocate-directive:
2582
///         annot_pragma_openmp 'allocate' simple-variable-list
2583
///         annot_pragma_openmp_end
2584
///
2585
///       declare-reduction-directive:
2586
///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
2587
///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
2588
///         ('omp_priv' '=' <expression>|<function_call>) ')']
2589
///         annot_pragma_openmp_end
2590
///
2591
///       declare-mapper-directive:
2592
///         annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
2593
///         <type> <var> ')' [<clause>[[,] <clause>] ... ]
2594
///         annot_pragma_openmp_end
2595
///
2596
///       executable-directive:
2597
///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
2598
///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
2599
///         'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
2600
///         'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error'
2601
///         | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
2602
///         data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
2603
///         'master taskloop' | 'master taskloop simd' | 'parallel master
2604
///         taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
2605
///         enter data' | 'target exit data' | 'target parallel' | 'target
2606
///         parallel for' | 'target update' | 'distribute parallel for' |
2607
///         'distribute paralle for simd' | 'distribute simd' | 'target parallel
2608
///         for simd' | 'target simd' | 'teams distribute' | 'teams distribute
2609
///         simd' | 'teams distribute parallel for simd' | 'teams distribute
2610
///         parallel for' | 'target teams' | 'target teams distribute' | 'target
2611
///         teams distribute parallel for' | 'target teams distribute parallel
2612
///         for simd' | 'target teams distribute simd' | 'masked' |
2613
///         'parallel masked' {clause} annot_pragma_openmp_end
2614
///
2615
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2616
    ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2617
  if (!ReadDirectiveWithinMetadirective)
2618
    assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2619
           "Not an OpenMP directive!");
2620
  ParsingOpenMPDirectiveRAII DirScope(*this);
2621
  ParenBraceBracketBalancer BalancerRAIIObj(*this);
2622
  SourceLocation Loc = ReadDirectiveWithinMetadirective
2623
                           ? Tok.getLocation()
2624
                           : ConsumeAnnotationToken();
2625
  OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
2626
  if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2627
    Diag(Tok, diag::err_omp_unknown_directive);
2628
    return StmtError();
2629
  }
2630

2631
  StmtResult Directive = StmtError();
2632

2633
  bool IsExecutable = [&]() {
2634
    if (DKind == OMPD_error) // OMPD_error is handled as executable
2635
      return true;
2636
    auto Res = getDirectiveCategory(DKind);
2637
    return Res == Category::Executable || Res == Category::Subsidiary;
2638
  }();
2639

2640
  if (IsExecutable) {
2641
    Directive = ParseOpenMPExecutableDirective(
2642
        StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2643
    assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2644
    return Directive;
2645
  }
2646

2647
  switch (DKind) {
2648
  case OMPD_nothing:
2649
    ConsumeToken();
2650
    // If we are parsing the directive within a metadirective, the directive
2651
    // ends with a ')'.
2652
    if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
2653
      while (Tok.isNot(tok::annot_pragma_openmp_end))
2654
        ConsumeAnyToken();
2655
    else
2656
      skipUntilPragmaOpenMPEnd(DKind);
2657
    if (Tok.is(tok::annot_pragma_openmp_end))
2658
      ConsumeAnnotationToken();
2659
    // return an empty statement
2660
    return StmtEmpty();
2661
  case OMPD_metadirective: {
2662
    ConsumeToken();
2663
    SmallVector<VariantMatchInfo, 4> VMIs;
2664

2665
    // First iteration of parsing all clauses of metadirective.
2666
    // This iteration only parses and collects all context selector ignoring the
2667
    // associated directives.
2668
    TentativeParsingAction TPA(*this);
2669
    ASTContext &ASTContext = Actions.getASTContext();
2670

2671
    BalancedDelimiterTracker T(*this, tok::l_paren,
2672
                               tok::annot_pragma_openmp_end);
2673
    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2674
      OpenMPClauseKind CKind = Tok.isAnnotation()
2675
                                   ? OMPC_unknown
2676
                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
2677
      SourceLocation Loc = ConsumeToken();
2678

2679
      // Parse '('.
2680
      if (T.expectAndConsume(diag::err_expected_lparen_after,
2681
                             getOpenMPClauseName(CKind).data()))
2682
        return Directive;
2683

2684
      OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2685
      if (CKind == OMPC_when) {
2686
        // parse and get OMPTraitInfo to pass to the When clause
2687
        parseOMPContextSelectors(Loc, TI);
2688
        if (TI.Sets.size() == 0) {
2689
          Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
2690
          TPA.Commit();
2691
          return Directive;
2692
        }
2693

2694
        // Parse ':'
2695
        if (Tok.is(tok::colon))
2696
          ConsumeAnyToken();
2697
        else {
2698
          Diag(Tok, diag::err_omp_expected_colon) << "when clause";
2699
          TPA.Commit();
2700
          return Directive;
2701
        }
2702
      }
2703
      // Skip Directive for now. We will parse directive in the second iteration
2704
      int paren = 0;
2705
      while (Tok.isNot(tok::r_paren) || paren != 0) {
2706
        if (Tok.is(tok::l_paren))
2707
          paren++;
2708
        if (Tok.is(tok::r_paren))
2709
          paren--;
2710
        if (Tok.is(tok::annot_pragma_openmp_end)) {
2711
          Diag(Tok, diag::err_omp_expected_punc)
2712
              << getOpenMPClauseName(CKind) << 0;
2713
          TPA.Commit();
2714
          return Directive;
2715
        }
2716
        ConsumeAnyToken();
2717
      }
2718
      // Parse ')'
2719
      if (Tok.is(tok::r_paren))
2720
        T.consumeClose();
2721

2722
      VariantMatchInfo VMI;
2723
      TI.getAsVariantMatchInfo(ASTContext, VMI);
2724

2725
      VMIs.push_back(VMI);
2726
    }
2727

2728
    TPA.Revert();
2729
    // End of the first iteration. Parser is reset to the start of metadirective
2730

2731
    std::function<void(StringRef)> DiagUnknownTrait =
2732
        [this, Loc](StringRef ISATrait) {
2733
          // TODO Track the selector locations in a way that is accessible here
2734
          // to improve the diagnostic location.
2735
          Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2736
        };
2737
    TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2738
                            /* CurrentFunctionDecl */ nullptr,
2739
                            ArrayRef<llvm::omp::TraitProperty>());
2740

2741
    // A single match is returned for OpenMP 5.0
2742
    int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2743

2744
    int Idx = 0;
2745
    // In OpenMP 5.0 metadirective is either replaced by another directive or
2746
    // ignored.
2747
    // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2748
    // found by getBestWhenMatchForContext.
2749
    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2750
      // OpenMP 5.0 implementation - Skip to the best index found.
2751
      if (Idx++ != BestIdx) {
2752
        ConsumeToken();  // Consume clause name
2753
        T.consumeOpen(); // Consume '('
2754
        int paren = 0;
2755
        // Skip everything inside the clause
2756
        while (Tok.isNot(tok::r_paren) || paren != 0) {
2757
          if (Tok.is(tok::l_paren))
2758
            paren++;
2759
          if (Tok.is(tok::r_paren))
2760
            paren--;
2761
          ConsumeAnyToken();
2762
        }
2763
        // Parse ')'
2764
        if (Tok.is(tok::r_paren))
2765
          T.consumeClose();
2766
        continue;
2767
      }
2768

2769
      OpenMPClauseKind CKind = Tok.isAnnotation()
2770
                                   ? OMPC_unknown
2771
                                   : getOpenMPClauseKind(PP.getSpelling(Tok));
2772
      SourceLocation Loc = ConsumeToken();
2773

2774
      // Parse '('.
2775
      T.consumeOpen();
2776

2777
      // Skip ContextSelectors for when clause
2778
      if (CKind == OMPC_when) {
2779
        OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2780
        // parse and skip the ContextSelectors
2781
        parseOMPContextSelectors(Loc, TI);
2782

2783
        // Parse ':'
2784
        ConsumeAnyToken();
2785
      }
2786

2787
      // If no directive is passed, skip in OpenMP 5.0.
2788
      // TODO: Generate nothing directive from OpenMP 5.1.
2789
      if (Tok.is(tok::r_paren)) {
2790
        SkipUntil(tok::annot_pragma_openmp_end);
2791
        break;
2792
      }
2793

2794
      // Parse Directive
2795
      Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2796
          StmtCtx,
2797
          /*ReadDirectiveWithinMetadirective=*/true);
2798
      break;
2799
    }
2800
    break;
2801
  }
2802
  case OMPD_threadprivate: {
2803
    // FIXME: Should this be permitted in C++?
2804
    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2805
        ParsedStmtContext()) {
2806
      Diag(Tok, diag::err_omp_immediate_directive)
2807
          << getOpenMPDirectiveName(DKind) << 0;
2808
    }
2809
    ConsumeToken();
2810
    DeclDirectiveListParserHelper Helper(this, DKind);
2811
    if (!ParseOpenMPSimpleVarList(DKind, Helper,
2812
                                  /*AllowScopeSpecifier=*/false)) {
2813
      skipUntilPragmaOpenMPEnd(DKind);
2814
      DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2815
          Loc, Helper.getIdentifiers());
2816
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2817
    }
2818
    SkipUntil(tok::annot_pragma_openmp_end);
2819
    break;
2820
  }
2821
  case OMPD_allocate: {
2822
    // FIXME: Should this be permitted in C++?
2823
    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2824
        ParsedStmtContext()) {
2825
      Diag(Tok, diag::err_omp_immediate_directive)
2826
          << getOpenMPDirectiveName(DKind) << 0;
2827
    }
2828
    ConsumeToken();
2829
    DeclDirectiveListParserHelper Helper(this, DKind);
2830
    if (!ParseOpenMPSimpleVarList(DKind, Helper,
2831
                                  /*AllowScopeSpecifier=*/false)) {
2832
      SmallVector<OMPClause *, 1> Clauses;
2833
      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2834
        llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2835
        while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2836
          OpenMPClauseKind CKind =
2837
              Tok.isAnnotation() ? OMPC_unknown
2838
                                 : getOpenMPClauseKind(PP.getSpelling(Tok));
2839
          Actions.OpenMP().StartOpenMPClause(CKind);
2840
          OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2841
                                                !SeenClauses[unsigned(CKind)]);
2842
          SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2843
                    StopBeforeMatch);
2844
          SeenClauses[unsigned(CKind)] = true;
2845
          if (Clause != nullptr)
2846
            Clauses.push_back(Clause);
2847
          if (Tok.is(tok::annot_pragma_openmp_end)) {
2848
            Actions.OpenMP().EndOpenMPClause();
2849
            break;
2850
          }
2851
          // Skip ',' if any.
2852
          if (Tok.is(tok::comma))
2853
            ConsumeToken();
2854
          Actions.OpenMP().EndOpenMPClause();
2855
        }
2856
        skipUntilPragmaOpenMPEnd(DKind);
2857
      }
2858
      DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
2859
          Loc, Helper.getIdentifiers(), Clauses);
2860
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2861
    }
2862
    SkipUntil(tok::annot_pragma_openmp_end);
2863
    break;
2864
  }
2865
  case OMPD_declare_reduction:
2866
    ConsumeToken();
2867
    if (DeclGroupPtrTy Res =
2868
            ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2869
      skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2870
      ConsumeAnyToken();
2871
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2872
    } else {
2873
      SkipUntil(tok::annot_pragma_openmp_end);
2874
    }
2875
    break;
2876
  case OMPD_declare_mapper: {
2877
    ConsumeToken();
2878
    if (DeclGroupPtrTy Res =
2879
            ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2880
      // Skip the last annot_pragma_openmp_end.
2881
      ConsumeAnnotationToken();
2882
      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2883
    } else {
2884
      SkipUntil(tok::annot_pragma_openmp_end);
2885
    }
2886
    break;
2887
  }
2888
  case OMPD_declare_target: {
2889
    SourceLocation DTLoc = ConsumeAnyToken();
2890
    bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2891
    SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2892
    if (HasClauses)
2893
      ParseOMPDeclareTargetClauses(DTCI);
2894
    bool HasImplicitMappings =
2895
        !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2896

2897
    if (HasImplicitMappings) {
2898
      Diag(Tok, diag::err_omp_unexpected_directive)
2899
          << 1 << getOpenMPDirectiveName(DKind);
2900
      SkipUntil(tok::annot_pragma_openmp_end);
2901
      break;
2902
    }
2903

2904
    // Skip the last annot_pragma_openmp_end.
2905
    ConsumeAnyToken();
2906

2907
    Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
2908
    break;
2909
  }
2910
  case OMPD_declare_simd:
2911
  case OMPD_begin_declare_target:
2912
  case OMPD_end_declare_target:
2913
  case OMPD_requires:
2914
  case OMPD_begin_declare_variant:
2915
  case OMPD_end_declare_variant:
2916
  case OMPD_declare_variant:
2917
    Diag(Tok, diag::err_omp_unexpected_directive)
2918
        << 1 << getOpenMPDirectiveName(DKind);
2919
    SkipUntil(tok::annot_pragma_openmp_end);
2920
    break;
2921
  case OMPD_unknown:
2922
  default:
2923
    Diag(Tok, diag::err_omp_unknown_directive);
2924
    SkipUntil(tok::annot_pragma_openmp_end);
2925
    break;
2926
  }
2927
  return Directive;
2928
}
2929

2930
// Parses simple list:
2931
//   simple-variable-list:
2932
//         '(' id-expression {, id-expression} ')'
2933
//
2934
bool Parser::ParseOpenMPSimpleVarList(
2935
    OpenMPDirectiveKind Kind,
2936
    const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
2937
        &Callback,
2938
    bool AllowScopeSpecifier) {
2939
  // Parse '('.
2940
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
2941
  if (T.expectAndConsume(diag::err_expected_lparen_after,
2942
                         getOpenMPDirectiveName(Kind).data()))
2943
    return true;
2944
  bool IsCorrect = true;
2945
  bool NoIdentIsFound = true;
2946

2947
  // Read tokens while ')' or annot_pragma_openmp_end is not found.
2948
  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
2949
    CXXScopeSpec SS;
2950
    UnqualifiedId Name;
2951
    // Read var name.
2952
    Token PrevTok = Tok;
2953
    NoIdentIsFound = false;
2954

2955
    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2956
        ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2957
                                       /*ObjectHasErrors=*/false, false)) {
2958
      IsCorrect = false;
2959
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2960
                StopBeforeMatch);
2961
    } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2962
                                  /*ObjectHadErrors=*/false, false, false,
2963
                                  false, false, nullptr, Name)) {
2964
      IsCorrect = false;
2965
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2966
                StopBeforeMatch);
2967
    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
2968
               Tok.isNot(tok::annot_pragma_openmp_end)) {
2969
      IsCorrect = false;
2970
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2971
                StopBeforeMatch);
2972
      Diag(PrevTok.getLocation(), diag::err_expected)
2973
          << tok::identifier
2974
          << SourceRange(PrevTok.getLocation(), PrevTokLocation);
2975
    } else {
2976
      Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2977
    }
2978
    // Consume ','.
2979
    if (Tok.is(tok::comma)) {
2980
      ConsumeToken();
2981
    }
2982
  }
2983

2984
  if (NoIdentIsFound) {
2985
    Diag(Tok, diag::err_expected) << tok::identifier;
2986
    IsCorrect = false;
2987
  }
2988

2989
  // Parse ')'.
2990
  IsCorrect = !T.consumeClose() && IsCorrect;
2991

2992
  return !IsCorrect;
2993
}
2994

2995
OMPClause *Parser::ParseOpenMPSizesClause() {
2996
  SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
2997
  SmallVector<Expr *, 4> ValExprs;
2998
  if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
2999
                                ValExprs))
3000
    return nullptr;
3001

3002
  return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
3003
                                                 OpenLoc, CloseLoc);
3004
}
3005

3006
OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
3007
  SourceLocation Loc = Tok.getLocation();
3008
  ConsumeAnyToken();
3009

3010
  // Parse '('.
3011
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3012
  if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
3013
    return nullptr;
3014
  SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
3015
  do {
3016
    CXXScopeSpec SS;
3017
    Token Replacement;
3018
    ExprResult Allocator =
3019
        getLangOpts().CPlusPlus
3020
            ? ParseCXXIdExpression()
3021
            : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
3022
                                      Replacement);
3023
    if (Allocator.isInvalid()) {
3024
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3025
                StopBeforeMatch);
3026
      break;
3027
    }
3028
    SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3029
    D.Allocator = Allocator.get();
3030
    if (Tok.is(tok::l_paren)) {
3031
      BalancedDelimiterTracker T(*this, tok::l_paren,
3032
                                 tok::annot_pragma_openmp_end);
3033
      T.consumeOpen();
3034
      ExprResult AllocatorTraits =
3035
          getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3036
      T.consumeClose();
3037
      if (AllocatorTraits.isInvalid()) {
3038
        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3039
                  StopBeforeMatch);
3040
        break;
3041
      }
3042
      D.AllocatorTraits = AllocatorTraits.get();
3043
      D.LParenLoc = T.getOpenLocation();
3044
      D.RParenLoc = T.getCloseLocation();
3045
    }
3046
    if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3047
      Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
3048
    // Parse ','
3049
    if (Tok.is(tok::comma))
3050
      ConsumeAnyToken();
3051
  } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
3052
  T.consumeClose();
3053
  return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3054
      Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
3055
}
3056

3057
/// Parsing of OpenMP clauses.
3058
///
3059
///    clause:
3060
///       if-clause | final-clause | num_threads-clause | safelen-clause |
3061
///       default-clause | private-clause | firstprivate-clause | shared-clause
3062
///       | linear-clause | aligned-clause | collapse-clause | bind-clause |
3063
///       lastprivate-clause | reduction-clause | proc_bind-clause |
3064
///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
3065
///       mergeable-clause | flush-clause | read-clause | write-clause |
3066
///       update-clause | capture-clause | seq_cst-clause | device-clause |
3067
///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
3068
///       thread_limit-clause | priority-clause | grainsize-clause |
3069
///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
3070
///       from-clause | is_device_ptr-clause | task_reduction-clause |
3071
///       in_reduction-clause | allocator-clause | allocate-clause |
3072
///       acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
3073
///       depobj-clause | destroy-clause | detach-clause | inclusive-clause |
3074
///       exclusive-clause | uses_allocators-clause | use_device_addr-clause |
3075
///       has_device_addr
3076
///
3077
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
3078
                                     OpenMPClauseKind CKind, bool FirstClause) {
3079
  OMPClauseKind = CKind;
3080
  OMPClause *Clause = nullptr;
3081
  bool ErrorFound = false;
3082
  bool WrongDirective = false;
3083
  // Check if clause is allowed for the given directive.
3084
  if (CKind != OMPC_unknown &&
3085
      !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
3086
    Diag(Tok, diag::err_omp_unexpected_clause)
3087
        << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3088
    ErrorFound = true;
3089
    WrongDirective = true;
3090
  }
3091

3092
  switch (CKind) {
3093
  case OMPC_final:
3094
  case OMPC_num_threads:
3095
  case OMPC_safelen:
3096
  case OMPC_simdlen:
3097
  case OMPC_collapse:
3098
  case OMPC_ordered:
3099
  case OMPC_num_teams:
3100
  case OMPC_thread_limit:
3101
  case OMPC_priority:
3102
  case OMPC_grainsize:
3103
  case OMPC_num_tasks:
3104
  case OMPC_hint:
3105
  case OMPC_allocator:
3106
  case OMPC_depobj:
3107
  case OMPC_detach:
3108
  case OMPC_novariants:
3109
  case OMPC_nocontext:
3110
  case OMPC_filter:
3111
  case OMPC_partial:
3112
  case OMPC_align:
3113
  case OMPC_message:
3114
  case OMPC_ompx_dyn_cgroup_mem:
3115
    // OpenMP [2.5, Restrictions]
3116
    //  At most one num_threads clause can appear on the directive.
3117
    // OpenMP [2.8.1, simd construct, Restrictions]
3118
    //  Only one safelen  clause can appear on a simd directive.
3119
    //  Only one simdlen  clause can appear on a simd directive.
3120
    //  Only one collapse clause can appear on a simd directive.
3121
    // OpenMP [2.11.1, task Construct, Restrictions]
3122
    //  At most one if clause can appear on the directive.
3123
    //  At most one final clause can appear on the directive.
3124
    // OpenMP [teams Construct, Restrictions]
3125
    //  At most one num_teams clause can appear on the directive.
3126
    //  At most one thread_limit clause can appear on the directive.
3127
    // OpenMP [2.9.1, task Construct, Restrictions]
3128
    // At most one priority clause can appear on the directive.
3129
    // OpenMP [2.9.2, taskloop Construct, Restrictions]
3130
    // At most one grainsize clause can appear on the directive.
3131
    // OpenMP [2.9.2, taskloop Construct, Restrictions]
3132
    // At most one num_tasks clause can appear on the directive.
3133
    // OpenMP [2.11.3, allocate Directive, Restrictions]
3134
    // At most one allocator clause can appear on the directive.
3135
    // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3136
    // At most one detach clause can appear on the directive.
3137
    // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3138
    // At most one novariants clause can appear on a dispatch directive.
3139
    // At most one nocontext clause can appear on a dispatch directive.
3140
    // OpenMP [5.1, error directive, Restrictions]
3141
    // At most one message clause can appear on the directive
3142
    if (!FirstClause) {
3143
      Diag(Tok, diag::err_omp_more_one_clause)
3144
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3145
      ErrorFound = true;
3146
    }
3147

3148
    if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3149
        PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
3150
      Clause = ParseOpenMPClause(CKind, WrongDirective);
3151
    else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
3152
      Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3153
    else
3154
      Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3155
    break;
3156
  case OMPC_fail:
3157
  case OMPC_default:
3158
  case OMPC_proc_bind:
3159
  case OMPC_atomic_default_mem_order:
3160
  case OMPC_at:
3161
  case OMPC_severity:
3162
  case OMPC_bind:
3163
    // OpenMP [2.14.3.1, Restrictions]
3164
    //  Only a single default clause may be specified on a parallel, task or
3165
    //  teams directive.
3166
    // OpenMP [2.5, parallel Construct, Restrictions]
3167
    //  At most one proc_bind clause can appear on the directive.
3168
    // OpenMP [5.0, Requires directive, Restrictions]
3169
    //  At most one atomic_default_mem_order clause can appear
3170
    //  on the directive
3171
    // OpenMP [5.1, error directive, Restrictions]
3172
    //  At most one at clause can appear on the directive
3173
    //  At most one severity clause can appear on the directive
3174
    // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3175
    // At most one bind clause can appear on a loop directive.
3176
    if (!FirstClause) {
3177
      Diag(Tok, diag::err_omp_more_one_clause)
3178
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3179
      ErrorFound = true;
3180
    }
3181

3182
    Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3183
    break;
3184
  case OMPC_device:
3185
  case OMPC_schedule:
3186
  case OMPC_dist_schedule:
3187
  case OMPC_defaultmap:
3188
  case OMPC_order:
3189
    // OpenMP [2.7.1, Restrictions, p. 3]
3190
    //  Only one schedule clause can appear on a loop directive.
3191
    // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3192
    //  At most one defaultmap clause can appear on the directive.
3193
    // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3194
    //  At most one device clause can appear on the directive.
3195
    // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3196
    //  At most one order clause may appear on a construct.
3197
    if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3198
        (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3199
      Diag(Tok, diag::err_omp_more_one_clause)
3200
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3201
      ErrorFound = true;
3202
    }
3203
    [[fallthrough]];
3204
  case OMPC_if:
3205
    Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3206
    break;
3207
  case OMPC_nowait:
3208
  case OMPC_untied:
3209
  case OMPC_mergeable:
3210
  case OMPC_read:
3211
  case OMPC_write:
3212
  case OMPC_capture:
3213
  case OMPC_compare:
3214
  case OMPC_seq_cst:
3215
  case OMPC_acq_rel:
3216
  case OMPC_acquire:
3217
  case OMPC_release:
3218
  case OMPC_relaxed:
3219
  case OMPC_weak:
3220
  case OMPC_threads:
3221
  case OMPC_simd:
3222
  case OMPC_nogroup:
3223
  case OMPC_unified_address:
3224
  case OMPC_unified_shared_memory:
3225
  case OMPC_reverse_offload:
3226
  case OMPC_dynamic_allocators:
3227
  case OMPC_full:
3228
    // OpenMP [2.7.1, Restrictions, p. 9]
3229
    //  Only one ordered clause can appear on a loop directive.
3230
    // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3231
    //  Only one nowait clause can appear on a for directive.
3232
    // OpenMP [5.0, Requires directive, Restrictions]
3233
    //   Each of the requires clauses can appear at most once on the directive.
3234
    if (!FirstClause) {
3235
      Diag(Tok, diag::err_omp_more_one_clause)
3236
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3237
      ErrorFound = true;
3238
    }
3239

3240
    Clause = ParseOpenMPClause(CKind, WrongDirective);
3241
    break;
3242
  case OMPC_update:
3243
    if (!FirstClause) {
3244
      Diag(Tok, diag::err_omp_more_one_clause)
3245
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3246
      ErrorFound = true;
3247
    }
3248

3249
    Clause = (DKind == OMPD_depobj)
3250
                 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
3251
                 : ParseOpenMPClause(CKind, WrongDirective);
3252
    break;
3253
  case OMPC_private:
3254
  case OMPC_firstprivate:
3255
  case OMPC_lastprivate:
3256
  case OMPC_shared:
3257
  case OMPC_reduction:
3258
  case OMPC_task_reduction:
3259
  case OMPC_in_reduction:
3260
  case OMPC_linear:
3261
  case OMPC_aligned:
3262
  case OMPC_copyin:
3263
  case OMPC_copyprivate:
3264
  case OMPC_flush:
3265
  case OMPC_depend:
3266
  case OMPC_map:
3267
  case OMPC_to:
3268
  case OMPC_from:
3269
  case OMPC_use_device_ptr:
3270
  case OMPC_use_device_addr:
3271
  case OMPC_is_device_ptr:
3272
  case OMPC_has_device_addr:
3273
  case OMPC_allocate:
3274
  case OMPC_nontemporal:
3275
  case OMPC_inclusive:
3276
  case OMPC_exclusive:
3277
  case OMPC_affinity:
3278
  case OMPC_doacross:
3279
  case OMPC_enter:
3280
    if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
3281
        CKind == OMPC_depend)
3282
      Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3283
    Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3284
    break;
3285
  case OMPC_sizes:
3286
    if (!FirstClause) {
3287
      Diag(Tok, diag::err_omp_more_one_clause)
3288
          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3289
      ErrorFound = true;
3290
    }
3291

3292
    Clause = ParseOpenMPSizesClause();
3293
    break;
3294
  case OMPC_uses_allocators:
3295
    Clause = ParseOpenMPUsesAllocatorClause(DKind);
3296
    break;
3297
  case OMPC_destroy:
3298
    if (DKind != OMPD_interop) {
3299
      if (!FirstClause) {
3300
        Diag(Tok, diag::err_omp_more_one_clause)
3301
            << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3302
        ErrorFound = true;
3303
      }
3304
      Clause = ParseOpenMPClause(CKind, WrongDirective);
3305
      break;
3306
    }
3307
    [[fallthrough]];
3308
  case OMPC_init:
3309
  case OMPC_use:
3310
    Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3311
    break;
3312
  case OMPC_device_type:
3313
  case OMPC_unknown:
3314
    skipUntilPragmaOpenMPEnd(DKind);
3315
    break;
3316
  case OMPC_threadprivate:
3317
  case OMPC_uniform:
3318
  case OMPC_match:
3319
    if (!WrongDirective)
3320
      Diag(Tok, diag::err_omp_unexpected_clause)
3321
          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3322
    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
3323
    break;
3324
  case OMPC_ompx_attribute:
3325
    Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3326
    break;
3327
  case OMPC_ompx_bare:
3328
    if (WrongDirective)
3329
      Diag(Tok, diag::note_ompx_bare_clause)
3330
          << getOpenMPClauseName(CKind) << "target teams";
3331
    if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3332
      Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3333
          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3334
      ErrorFound = true;
3335
    }
3336
    Clause = ParseOpenMPClause(CKind, WrongDirective);
3337
    break;
3338
  default:
3339
    break;
3340
  }
3341
  return ErrorFound ? nullptr : Clause;
3342
}
3343

3344
/// Parses simple expression in parens for single-expression clauses of OpenMP
3345
/// constructs.
3346
/// \param RLoc Returned location of right paren.
3347
ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
3348
                                         SourceLocation &RLoc,
3349
                                         bool IsAddressOfOperand) {
3350
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3351
  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3352
    return ExprError();
3353

3354
  SourceLocation ELoc = Tok.getLocation();
3355
  ExprResult LHS(
3356
      ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast));
3357
  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3358
  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3359

3360
  // Parse ')'.
3361
  RLoc = Tok.getLocation();
3362
  if (!T.consumeClose())
3363
    RLoc = T.getCloseLocation();
3364

3365
  return Val;
3366
}
3367

3368
/// Parsing of OpenMP clauses with single expressions like 'final',
3369
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
3370
/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
3371
/// 'detach'.
3372
///
3373
///    final-clause:
3374
///      'final' '(' expression ')'
3375
///
3376
///    num_threads-clause:
3377
///      'num_threads' '(' expression ')'
3378
///
3379
///    safelen-clause:
3380
///      'safelen' '(' expression ')'
3381
///
3382
///    simdlen-clause:
3383
///      'simdlen' '(' expression ')'
3384
///
3385
///    collapse-clause:
3386
///      'collapse' '(' expression ')'
3387
///
3388
///    priority-clause:
3389
///      'priority' '(' expression ')'
3390
///
3391
///    grainsize-clause:
3392
///      'grainsize' '(' expression ')'
3393
///
3394
///    num_tasks-clause:
3395
///      'num_tasks' '(' expression ')'
3396
///
3397
///    hint-clause:
3398
///      'hint' '(' expression ')'
3399
///
3400
///    allocator-clause:
3401
///      'allocator' '(' expression ')'
3402
///
3403
///    detach-clause:
3404
///      'detach' '(' event-handler-expression ')'
3405
///
3406
///    align-clause
3407
///      'align' '(' positive-integer-constant ')'
3408
///
3409
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3410
                                               bool ParseOnly) {
3411
  SourceLocation Loc = ConsumeToken();
3412
  SourceLocation LLoc = Tok.getLocation();
3413
  SourceLocation RLoc;
3414

3415
  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
3416

3417
  if (Val.isInvalid())
3418
    return nullptr;
3419

3420
  if (ParseOnly)
3421
    return nullptr;
3422
  return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3423
                                                      LLoc, RLoc);
3424
}
3425

3426
/// Parse indirect clause for '#pragma omp declare target' directive.
3427
///  'indirect' '[' '(' invoked-by-fptr ')' ']'
3428
/// where invoked-by-fptr is a constant boolean expression that evaluates to
3429
/// true or false at compile time.
3430
bool Parser::ParseOpenMPIndirectClause(
3431
    SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3432
  SourceLocation Loc = ConsumeToken();
3433
  SourceLocation RLoc;
3434

3435
  if (Tok.isNot(tok::l_paren)) {
3436
    if (ParseOnly)
3437
      return false;
3438
    DTCI.Indirect = nullptr;
3439
    return true;
3440
  }
3441

3442
  ExprResult Val =
3443
      ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3444
  if (Val.isInvalid())
3445
    return false;
3446

3447
  if (ParseOnly)
3448
    return false;
3449

3450
  if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3451
      !Val.get()->isInstantiationDependent() &&
3452
      !Val.get()->containsUnexpandedParameterPack()) {
3453
    ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3454
    if (Ret.isInvalid())
3455
      return false;
3456
    llvm::APSInt Result;
3457
    Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
3458
                                                  Sema::AllowFold);
3459
    if (Ret.isInvalid())
3460
      return false;
3461
    DTCI.Indirect = Val.get();
3462
    return true;
3463
  }
3464
  return false;
3465
}
3466

3467
/// Parses a comma-separated list of interop-types and a prefer_type list.
3468
///
3469
bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3470
                                 OpenMPClauseKind Kind) {
3471
  const Token &Tok = getCurToken();
3472
  bool HasError = false;
3473
  bool IsTarget = false;
3474
  bool IsTargetSync = false;
3475

3476
  while (Tok.is(tok::identifier)) {
3477
    // Currently prefer_type is only allowed with 'init' and it must be first.
3478
    bool PreferTypeAllowed = Kind == OMPC_init &&
3479
                             InteropInfo.PreferTypes.empty() && !IsTarget &&
3480
                             !IsTargetSync;
3481
    if (Tok.getIdentifierInfo()->isStr("target")) {
3482
      // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3483
      // Each interop-type may be specified on an action-clause at most
3484
      // once.
3485
      if (IsTarget)
3486
        Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3487
      IsTarget = true;
3488
      ConsumeToken();
3489
    } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3490
      if (IsTargetSync)
3491
        Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3492
      IsTargetSync = true;
3493
      ConsumeToken();
3494
    } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3495
               PreferTypeAllowed) {
3496
      ConsumeToken();
3497
      BalancedDelimiterTracker PT(*this, tok::l_paren,
3498
                                  tok::annot_pragma_openmp_end);
3499
      if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3500
        HasError = true;
3501

3502
      while (Tok.isNot(tok::r_paren)) {
3503
        SourceLocation Loc = Tok.getLocation();
3504
        ExprResult LHS = ParseCastExpression(AnyCastExpr);
3505
        ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
3506
            ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3507
        PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3508
                                             /*DiscardedValue=*/false);
3509
        if (PTExpr.isUsable()) {
3510
          InteropInfo.PreferTypes.push_back(PTExpr.get());
3511
        } else {
3512
          HasError = true;
3513
          SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3514
                    StopBeforeMatch);
3515
        }
3516

3517
        if (Tok.is(tok::comma))
3518
          ConsumeToken();
3519
      }
3520
      PT.consumeClose();
3521
    } else {
3522
      HasError = true;
3523
      Diag(Tok, diag::err_omp_expected_interop_type);
3524
      ConsumeToken();
3525
    }
3526
    if (!Tok.is(tok::comma))
3527
      break;
3528
    ConsumeToken();
3529
  }
3530

3531
  if (!HasError && !IsTarget && !IsTargetSync) {
3532
    Diag(Tok, diag::err_omp_expected_interop_type);
3533
    HasError = true;
3534
  }
3535

3536
  if (Kind == OMPC_init) {
3537
    if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
3538
      Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3539
    if (Tok.is(tok::colon))
3540
      ConsumeToken();
3541
  }
3542

3543
  // As of OpenMP 5.1,there are two interop-types, "target" and
3544
  // "targetsync". Either or both are allowed for a single interop.
3545
  InteropInfo.IsTarget = IsTarget;
3546
  InteropInfo.IsTargetSync = IsTargetSync;
3547

3548
  return HasError;
3549
}
3550

3551
/// Parsing of OpenMP clauses that use an interop-var.
3552
///
3553
/// init-clause:
3554
///   init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
3555
///
3556
/// destroy-clause:
3557
///   destroy(interop-var)
3558
///
3559
/// use-clause:
3560
///   use(interop-var)
3561
///
3562
/// interop-modifier:
3563
///   prefer_type(preference-list)
3564
///
3565
/// preference-list:
3566
///   foreign-runtime-id [, foreign-runtime-id]...
3567
///
3568
/// foreign-runtime-id:
3569
///   <string-literal> | <constant-integral-expression>
3570
///
3571
/// interop-type:
3572
///   target | targetsync
3573
///
3574
OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3575
                                            bool ParseOnly) {
3576
  SourceLocation Loc = ConsumeToken();
3577
  // Parse '('.
3578
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3579
  if (T.expectAndConsume(diag::err_expected_lparen_after,
3580
                         getOpenMPClauseName(Kind).data()))
3581
    return nullptr;
3582

3583
  bool InteropError = false;
3584
  OMPInteropInfo InteropInfo;
3585
  if (Kind == OMPC_init)
3586
    InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3587

3588
  // Parse the variable.
3589
  SourceLocation VarLoc = Tok.getLocation();
3590
  ExprResult InteropVarExpr =
3591
      Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
3592
  if (!InteropVarExpr.isUsable()) {
3593
    SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3594
              StopBeforeMatch);
3595
  }
3596

3597
  // Parse ')'.
3598
  SourceLocation RLoc = Tok.getLocation();
3599
  if (!T.consumeClose())
3600
    RLoc = T.getCloseLocation();
3601

3602
  if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3603
    return nullptr;
3604

3605
  if (Kind == OMPC_init)
3606
    return Actions.OpenMP().ActOnOpenMPInitClause(
3607
        InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
3608
        RLoc);
3609
  if (Kind == OMPC_use)
3610
    return Actions.OpenMP().ActOnOpenMPUseClause(
3611
        InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3612

3613
  if (Kind == OMPC_destroy)
3614
    return Actions.OpenMP().ActOnOpenMPDestroyClause(
3615
        InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3616

3617
  llvm_unreachable("Unexpected interop variable clause.");
3618
}
3619

3620
OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
3621
  SourceLocation Loc = ConsumeToken();
3622
  // Parse '('.
3623
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3624
  if (T.expectAndConsume(diag::err_expected_lparen_after,
3625
                         getOpenMPClauseName(OMPC_ompx_attribute).data()))
3626
    return nullptr;
3627

3628
  ParsedAttributes ParsedAttrs(AttrFactory);
3629
  ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
3630

3631
  // Parse ')'.
3632
  if (T.consumeClose())
3633
    return nullptr;
3634

3635
  if (ParseOnly)
3636
    return nullptr;
3637

3638
  SmallVector<Attr *> Attrs;
3639
  for (const ParsedAttr &PA : ParsedAttrs) {
3640
    switch (PA.getKind()) {
3641
    case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
3642
      if (!PA.checkExactlyNumArgs(Actions, 2))
3643
        continue;
3644
      if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
3645
              PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
3646
        Attrs.push_back(A);
3647
      continue;
3648
    case ParsedAttr::AT_AMDGPUWavesPerEU:
3649
      if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3650
          !PA.checkAtMostNumArgs(Actions, 2))
3651
        continue;
3652
      if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
3653
              PA, PA.getArgAsExpr(0),
3654
              PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
3655
        Attrs.push_back(A);
3656
      continue;
3657
    case ParsedAttr::AT_CUDALaunchBounds:
3658
      if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3659
          !PA.checkAtMostNumArgs(Actions, 2))
3660
        continue;
3661
      if (auto *A = Actions.CreateLaunchBoundsAttr(
3662
              PA, PA.getArgAsExpr(0),
3663
              PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
3664
              PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
3665
        Attrs.push_back(A);
3666
      continue;
3667
    default:
3668
      Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3669
      continue;
3670
    };
3671
  }
3672

3673
  return Actions.OpenMP().ActOnOpenMPXAttributeClause(
3674
      Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
3675
}
3676

3677
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
3678
///
3679
///    default-clause:
3680
///         'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')'
3681
///
3682
///    proc_bind-clause:
3683
///         'proc_bind' '(' 'master' | 'close' | 'spread' ')'
3684
///
3685
///    bind-clause:
3686
///         'bind' '(' 'teams' | 'parallel' | 'thread' ')'
3687
///
3688
///    update-clause:
3689
///         'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' |
3690
///         'inoutset' ')'
3691
///
3692
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
3693
                                           bool ParseOnly) {
3694
  std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
3695
  if (!Val || ParseOnly)
3696
    return nullptr;
3697
  if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3698
      (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
3699
       static_cast<DefaultKind>(Val->Type) ==
3700
           OMP_DEFAULT_firstprivate)) {
3701
    Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3702
        << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
3703
                                       OMP_DEFAULT_private
3704
                                   ? OMPC_private
3705
                                   : OMPC_firstprivate)
3706
        << getOpenMPClauseName(OMPC_default) << "5.1";
3707
    return nullptr;
3708
  }
3709
  return Actions.OpenMP().ActOnOpenMPSimpleClause(
3710
      Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
3711
}
3712

3713
/// Parsing of OpenMP clauses like 'ordered'.
3714
///
3715
///    ordered-clause:
3716
///         'ordered'
3717
///
3718
///    nowait-clause:
3719
///         'nowait'
3720
///
3721
///    untied-clause:
3722
///         'untied'
3723
///
3724
///    mergeable-clause:
3725
///         'mergeable'
3726
///
3727
///    read-clause:
3728
///         'read'
3729
///
3730
///    threads-clause:
3731
///         'threads'
3732
///
3733
///    simd-clause:
3734
///         'simd'
3735
///
3736
///    nogroup-clause:
3737
///         'nogroup'
3738
///
3739
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
3740
  SourceLocation Loc = Tok.getLocation();
3741
  ConsumeAnyToken();
3742

3743
  if (ParseOnly)
3744
    return nullptr;
3745
  return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
3746
}
3747

3748
/// Parsing of OpenMP clauses with single expressions and some additional
3749
/// argument like 'schedule' or 'dist_schedule'.
3750
///
3751
///    schedule-clause:
3752
///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
3753
///      ')'
3754
///
3755
///    if-clause:
3756
///      'if' '(' [ directive-name-modifier ':' ] expression ')'
3757
///
3758
///    defaultmap:
3759
///      'defaultmap' '(' modifier [ ':' kind ] ')'
3760
///
3761
///    device-clause:
3762
///      'device' '(' [ device-modifier ':' ] expression ')'
3763
///
3764
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
3765
                                                      OpenMPClauseKind Kind,
3766
                                                      bool ParseOnly) {
3767
  SourceLocation Loc = ConsumeToken();
3768
  SourceLocation DelimLoc;
3769
  // Parse '('.
3770
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3771
  if (T.expectAndConsume(diag::err_expected_lparen_after,
3772
                         getOpenMPClauseName(Kind).data()))
3773
    return nullptr;
3774

3775
  ExprResult Val;
3776
  SmallVector<unsigned, 4> Arg;
3777
  SmallVector<SourceLocation, 4> KLoc;
3778
  if (Kind == OMPC_schedule) {
3779
    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3780
    Arg.resize(NumberOfElements);
3781
    KLoc.resize(NumberOfElements);
3782
    Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
3783
    Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
3784
    Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
3785
    unsigned KindModifier = getOpenMPSimpleClauseType(
3786
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3787
    if (KindModifier > OMPC_SCHEDULE_unknown) {
3788
      // Parse 'modifier'
3789
      Arg[Modifier1] = KindModifier;
3790
      KLoc[Modifier1] = Tok.getLocation();
3791
      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3792
          Tok.isNot(tok::annot_pragma_openmp_end))
3793
        ConsumeAnyToken();
3794
      if (Tok.is(tok::comma)) {
3795
        // Parse ',' 'modifier'
3796
        ConsumeAnyToken();
3797
        KindModifier = getOpenMPSimpleClauseType(
3798
            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3799
        Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
3800
                             ? KindModifier
3801
                             : (unsigned)OMPC_SCHEDULE_unknown;
3802
        KLoc[Modifier2] = Tok.getLocation();
3803
        if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3804
            Tok.isNot(tok::annot_pragma_openmp_end))
3805
          ConsumeAnyToken();
3806
      }
3807
      // Parse ':'
3808
      if (Tok.is(tok::colon))
3809
        ConsumeAnyToken();
3810
      else
3811
        Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
3812
      KindModifier = getOpenMPSimpleClauseType(
3813
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3814
    }
3815
    Arg[ScheduleKind] = KindModifier;
3816
    KLoc[ScheduleKind] = Tok.getLocation();
3817
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3818
        Tok.isNot(tok::annot_pragma_openmp_end))
3819
      ConsumeAnyToken();
3820
    if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3821
         Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3822
         Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3823
        Tok.is(tok::comma))
3824
      DelimLoc = ConsumeAnyToken();
3825
  } else if (Kind == OMPC_dist_schedule) {
3826
    Arg.push_back(getOpenMPSimpleClauseType(
3827
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3828
    KLoc.push_back(Tok.getLocation());
3829
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3830
        Tok.isNot(tok::annot_pragma_openmp_end))
3831
      ConsumeAnyToken();
3832
    if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
3833
      DelimLoc = ConsumeAnyToken();
3834
  } else if (Kind == OMPC_defaultmap) {
3835
    // Get a defaultmap modifier
3836
    unsigned Modifier = getOpenMPSimpleClauseType(
3837
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3838
    // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
3839
    // pointer
3840
    if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
3841
      Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
3842
    Arg.push_back(Modifier);
3843
    KLoc.push_back(Tok.getLocation());
3844
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3845
        Tok.isNot(tok::annot_pragma_openmp_end))
3846
      ConsumeAnyToken();
3847
    // Parse ':'
3848
    if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
3849
      if (Tok.is(tok::colon))
3850
        ConsumeAnyToken();
3851
      else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
3852
        Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
3853
      // Get a defaultmap kind
3854
      Arg.push_back(getOpenMPSimpleClauseType(
3855
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3856
      KLoc.push_back(Tok.getLocation());
3857
      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3858
          Tok.isNot(tok::annot_pragma_openmp_end))
3859
        ConsumeAnyToken();
3860
    } else {
3861
      Arg.push_back(OMPC_DEFAULTMAP_unknown);
3862
      KLoc.push_back(SourceLocation());
3863
    }
3864
  } else if (Kind == OMPC_order) {
3865
    enum { Modifier, OrderKind, NumberOfElements };
3866
    Arg.resize(NumberOfElements);
3867
    KLoc.resize(NumberOfElements);
3868
    Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
3869
    Arg[OrderKind] = OMPC_ORDER_unknown;
3870
    unsigned KindModifier = getOpenMPSimpleClauseType(
3871
        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3872
    if (KindModifier > OMPC_ORDER_unknown) {
3873
      // Parse 'modifier'
3874
      Arg[Modifier] = KindModifier;
3875
      KLoc[Modifier] = Tok.getLocation();
3876
      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3877
          Tok.isNot(tok::annot_pragma_openmp_end))
3878
        ConsumeAnyToken();
3879
      // Parse ':'
3880
      if (Tok.is(tok::colon))
3881
        ConsumeAnyToken();
3882
      else
3883
        Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
3884
      KindModifier = getOpenMPSimpleClauseType(
3885
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3886
    }
3887
    Arg[OrderKind] = KindModifier;
3888
    KLoc[OrderKind] = Tok.getLocation();
3889
    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3890
        Tok.isNot(tok::annot_pragma_openmp_end))
3891
      ConsumeAnyToken();
3892
  } else if (Kind == OMPC_device) {
3893
    // Only target executable directives support extended device construct.
3894
    if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
3895
        NextToken().is(tok::colon)) {
3896
      // Parse optional <device modifier> ':'
3897
      Arg.push_back(getOpenMPSimpleClauseType(
3898
          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3899
      KLoc.push_back(Tok.getLocation());
3900
      ConsumeAnyToken();
3901
      // Parse ':'
3902
      ConsumeAnyToken();
3903
    } else {
3904
      Arg.push_back(OMPC_DEVICE_unknown);
3905
      KLoc.emplace_back();
3906
    }
3907
  } else if (Kind == OMPC_grainsize) {
3908
    // Parse optional <grainsize modifier> ':'
3909
    OpenMPGrainsizeClauseModifier Modifier =
3910
        static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType(
3911
            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3912
            getLangOpts()));
3913
    if (getLangOpts().OpenMP >= 51) {
3914
      if (NextToken().is(tok::colon)) {
3915
        Arg.push_back(Modifier);
3916
        KLoc.push_back(Tok.getLocation());
3917
        // Parse modifier
3918
        ConsumeAnyToken();
3919
        // Parse ':'
3920
        ConsumeAnyToken();
3921
      } else {
3922
        if (Modifier == OMPC_GRAINSIZE_strict) {
3923
          Diag(Tok, diag::err_modifier_expected_colon) << "strict";
3924
          // Parse modifier
3925
          ConsumeAnyToken();
3926
        }
3927
        Arg.push_back(OMPC_GRAINSIZE_unknown);
3928
        KLoc.emplace_back();
3929
      }
3930
    } else {
3931
      Arg.push_back(OMPC_GRAINSIZE_unknown);
3932
      KLoc.emplace_back();
3933
    }
3934
  } else if (Kind == OMPC_num_tasks) {
3935
    // Parse optional <num_tasks modifier> ':'
3936
    OpenMPNumTasksClauseModifier Modifier =
3937
        static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(
3938
            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
3939
            getLangOpts()));
3940
    if (getLangOpts().OpenMP >= 51) {
3941
      if (NextToken().is(tok::colon)) {
3942
        Arg.push_back(Modifier);
3943
        KLoc.push_back(Tok.getLocation());
3944
        // Parse modifier
3945
        ConsumeAnyToken();
3946
        // Parse ':'
3947
        ConsumeAnyToken();
3948
      } else {
3949
        if (Modifier == OMPC_NUMTASKS_strict) {
3950
          Diag(Tok, diag::err_modifier_expected_colon) << "strict";
3951
          // Parse modifier
3952
          ConsumeAnyToken();
3953
        }
3954
        Arg.push_back(OMPC_NUMTASKS_unknown);
3955
        KLoc.emplace_back();
3956
      }
3957
    } else {
3958
      Arg.push_back(OMPC_NUMTASKS_unknown);
3959
      KLoc.emplace_back();
3960
    }
3961
  } else {
3962
    assert(Kind == OMPC_if);
3963
    KLoc.push_back(Tok.getLocation());
3964
    TentativeParsingAction TPA(*this);
3965
    auto DK = parseOpenMPDirectiveKind(*this);
3966
    Arg.push_back(DK);
3967
    if (DK != OMPD_unknown) {
3968
      ConsumeToken();
3969
      if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
3970
        TPA.Commit();
3971
        DelimLoc = ConsumeToken();
3972
      } else {
3973
        TPA.Revert();
3974
        Arg.back() = unsigned(OMPD_unknown);
3975
      }
3976
    } else {
3977
      TPA.Revert();
3978
    }
3979
  }
3980

3981
  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
3982
                          (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
3983
                          Kind == OMPC_if || Kind == OMPC_device ||
3984
                          Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
3985
  if (NeedAnExpression) {
3986
    SourceLocation ELoc = Tok.getLocation();
3987
    ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
3988
    Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
3989
    Val =
3990
        Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3991
  }
3992

3993
  // Parse ')'.
3994
  SourceLocation RLoc = Tok.getLocation();
3995
  if (!T.consumeClose())
3996
    RLoc = T.getCloseLocation();
3997

3998
  if (NeedAnExpression && Val.isInvalid())
3999
    return nullptr;
4000

4001
  if (ParseOnly)
4002
    return nullptr;
4003
  return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4004
      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4005
}
4006

4007
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4008
                             UnqualifiedId &ReductionId) {
4009
  if (ReductionIdScopeSpec.isEmpty()) {
4010
    auto OOK = OO_None;
4011
    switch (P.getCurToken().getKind()) {
4012
    case tok::plus:
4013
      OOK = OO_Plus;
4014
      break;
4015
    case tok::minus:
4016
      OOK = OO_Minus;
4017
      break;
4018
    case tok::star:
4019
      OOK = OO_Star;
4020
      break;
4021
    case tok::amp:
4022
      OOK = OO_Amp;
4023
      break;
4024
    case tok::pipe:
4025
      OOK = OO_Pipe;
4026
      break;
4027
    case tok::caret:
4028
      OOK = OO_Caret;
4029
      break;
4030
    case tok::ampamp:
4031
      OOK = OO_AmpAmp;
4032
      break;
4033
    case tok::pipepipe:
4034
      OOK = OO_PipePipe;
4035
      break;
4036
    default:
4037
      break;
4038
    }
4039
    if (OOK != OO_None) {
4040
      SourceLocation OpLoc = P.ConsumeToken();
4041
      SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4042
      ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4043
      return false;
4044
    }
4045
  }
4046
  return P.ParseUnqualifiedId(
4047
      ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4048
      /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4049
      /*AllowDestructorName*/ false,
4050
      /*AllowConstructorName*/ false,
4051
      /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4052
}
4053

4054
/// Checks if the token is a valid map-type-modifier.
4055
/// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4056
static OpenMPMapModifierKind isMapModifier(Parser &P) {
4057
  Token Tok = P.getCurToken();
4058
  if (!Tok.is(tok::identifier))
4059
    return OMPC_MAP_MODIFIER_unknown;
4060

4061
  Preprocessor &PP = P.getPreprocessor();
4062
  OpenMPMapModifierKind TypeModifier =
4063
      static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType(
4064
          OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4065
  return TypeModifier;
4066
}
4067

4068
/// Parse the mapper modifier in map, to, and from clauses.
4069
bool Parser::parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data) {
4070
  // Parse '('.
4071
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4072
  if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4073
    SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4074
              StopBeforeMatch);
4075
    return true;
4076
  }
4077
  // Parse mapper-identifier
4078
  if (getLangOpts().CPlusPlus)
4079
    ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4080
                                   /*ObjectType=*/nullptr,
4081
                                   /*ObjectHasErrors=*/false,
4082
                                   /*EnteringContext=*/false);
4083
  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4084
    Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4085
    SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4086
              StopBeforeMatch);
4087
    return true;
4088
  }
4089
  auto &DeclNames = Actions.getASTContext().DeclarationNames;
4090
  Data.ReductionOrMapperId = DeclarationNameInfo(
4091
      DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4092
  ConsumeToken();
4093
  // Parse ')'.
4094
  return T.consumeClose();
4095
}
4096

4097
static OpenMPMapClauseKind isMapType(Parser &P);
4098

4099
/// Parse map-type-modifiers in map clause.
4100
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] [map-type] : ] list)
4101
/// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
4102
/// present
4103
/// where, map-type ::= alloc | delete | from | release | to | tofrom
4104
bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) {
4105
  bool HasMapType = false;
4106
  SourceLocation PreMapLoc = Tok.getLocation();
4107
  StringRef PreMapName = "";
4108
  while (getCurToken().isNot(tok::colon)) {
4109
    OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
4110
    OpenMPMapClauseKind MapKind = isMapType(*this);
4111
    if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4112
        TypeModifier == OMPC_MAP_MODIFIER_close ||
4113
        TypeModifier == OMPC_MAP_MODIFIER_present ||
4114
        TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4115
      Data.MapTypeModifiers.push_back(TypeModifier);
4116
      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4117
      if (PP.LookAhead(0).isNot(tok::comma) &&
4118
          PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4119
        Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4120
            << "map type modifier";
4121
      ConsumeToken();
4122
    } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4123
      Data.MapTypeModifiers.push_back(TypeModifier);
4124
      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4125
      ConsumeToken();
4126
      if (parseMapperModifier(Data))
4127
        return true;
4128
      if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4129
          getLangOpts().OpenMP >= 52)
4130
        Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4131
            << "map type modifier";
4132

4133
    } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4134
      if (!HasMapType) {
4135
        HasMapType = true;
4136
        Data.ExtraModifier = MapKind;
4137
        MapKind = OMPC_MAP_unknown;
4138
        PreMapLoc = Tok.getLocation();
4139
        PreMapName = Tok.getIdentifierInfo()->getName();
4140
      } else {
4141
        Diag(Tok, diag::err_omp_more_one_map_type);
4142
        Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4143
            << PreMapName;
4144
      }
4145
      ConsumeToken();
4146
    } else {
4147
      // For the case of unknown map-type-modifier or a map-type.
4148
      // Map-type is followed by a colon; the function returns when it
4149
      // encounters a token followed by a colon.
4150
      if (Tok.is(tok::comma)) {
4151
        Diag(Tok, diag::err_omp_map_type_modifier_missing);
4152
        ConsumeToken();
4153
        continue;
4154
      }
4155
      // Potential map-type token as it is followed by a colon.
4156
      if (PP.LookAhead(0).is(tok::colon)) {
4157
        if (getLangOpts().OpenMP >= 60) {
4158
          break;
4159
        } else {
4160
          return false;
4161
        }
4162
      }
4163

4164
      Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4165
          << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4166
                                         : 0)
4167
          << getLangOpts().OpenMPExtensions;
4168
      ConsumeToken();
4169
    }
4170
    if (getCurToken().is(tok::comma))
4171
      ConsumeToken();
4172
  }
4173
  if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4174
    if (!Tok.is(tok::colon)) {
4175
      Diag(Tok, diag::err_omp_unknown_map_type);
4176
      ConsumeToken();
4177
    } else {
4178
      Data.ExtraModifier = OMPC_MAP_unknown;
4179
    }
4180
  }
4181
  return false;
4182
}
4183

4184
/// Checks if the token is a valid map-type.
4185
/// If it is not MapType kind, OMPC_MAP_unknown is returned.
4186
static OpenMPMapClauseKind isMapType(Parser &P) {
4187
  Token Tok = P.getCurToken();
4188
  // The map-type token can be either an identifier or the C++ delete keyword.
4189
  if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4190
    return OMPC_MAP_unknown;
4191
  Preprocessor &PP = P.getPreprocessor();
4192
  unsigned MapType =
4193
      getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok), P.getLangOpts());
4194
  if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4195
      MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4196
      MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4197
    return static_cast<OpenMPMapClauseKind>(MapType);
4198
  return OMPC_MAP_unknown;
4199
}
4200

4201
/// Parse map-type in map clause.
4202
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4203
/// where, map-type ::= to | from | tofrom | alloc | release | delete
4204
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data) {
4205
  Token Tok = P.getCurToken();
4206
  if (Tok.is(tok::colon)) {
4207
    P.Diag(Tok, diag::err_omp_map_type_missing);
4208
    return;
4209
  }
4210
  Data.ExtraModifier = isMapType(P);
4211
  if (Data.ExtraModifier == OMPC_MAP_unknown)
4212
    P.Diag(Tok, diag::err_omp_unknown_map_type);
4213
  P.ConsumeToken();
4214
}
4215

4216
/// Parses simple expression in parens for single-expression clauses of OpenMP
4217
/// constructs.
4218
ExprResult Parser::ParseOpenMPIteratorsExpr() {
4219
  assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4220
         "Expected 'iterator' token.");
4221
  SourceLocation IteratorKwLoc = ConsumeToken();
4222

4223
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4224
  if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4225
    return ExprError();
4226

4227
  SourceLocation LLoc = T.getOpenLocation();
4228
  SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;
4229
  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4230
    // Check if the type parsing is required.
4231
    ParsedType IteratorType;
4232
    if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4233
      // identifier '=' is not found - parse type.
4234
      TypeResult TR = ParseTypeName();
4235
      if (TR.isInvalid()) {
4236
        T.skipToEnd();
4237
        return ExprError();
4238
      }
4239
      IteratorType = TR.get();
4240
    }
4241

4242
    // Parse identifier.
4243
    IdentifierInfo *II = nullptr;
4244
    SourceLocation IdLoc;
4245
    if (Tok.is(tok::identifier)) {
4246
      II = Tok.getIdentifierInfo();
4247
      IdLoc = ConsumeToken();
4248
    } else {
4249
      Diag(Tok, diag::err_expected_unqualified_id) << 0;
4250
    }
4251

4252
    // Parse '='.
4253
    SourceLocation AssignLoc;
4254
    if (Tok.is(tok::equal))
4255
      AssignLoc = ConsumeToken();
4256
    else
4257
      Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4258

4259
    // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4260
    ColonProtectionRAIIObject ColonRAII(*this);
4261
    // Parse <begin>
4262
    SourceLocation Loc = Tok.getLocation();
4263
    ExprResult LHS = ParseCastExpression(AnyCastExpr);
4264
    ExprResult Begin = Actions.CorrectDelayedTyposInExpr(
4265
        ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4266
    Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4267
                                        /*DiscardedValue=*/false);
4268
    // Parse ':'.
4269
    SourceLocation ColonLoc;
4270
    if (Tok.is(tok::colon))
4271
      ColonLoc = ConsumeToken();
4272

4273
    // Parse <end>
4274
    Loc = Tok.getLocation();
4275
    LHS = ParseCastExpression(AnyCastExpr);
4276
    ExprResult End = Actions.CorrectDelayedTyposInExpr(
4277
        ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4278
    End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4279
                                      /*DiscardedValue=*/false);
4280

4281
    SourceLocation SecColonLoc;
4282
    ExprResult Step;
4283
    // Parse optional step.
4284
    if (Tok.is(tok::colon)) {
4285
      // Parse ':'
4286
      SecColonLoc = ConsumeToken();
4287
      // Parse <step>
4288
      Loc = Tok.getLocation();
4289
      LHS = ParseCastExpression(AnyCastExpr);
4290
      Step = Actions.CorrectDelayedTyposInExpr(
4291
          ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4292
      Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4293
                                         /*DiscardedValue=*/false);
4294
    }
4295

4296
    // Parse ',' or ')'
4297
    if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4298
      Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4299
    if (Tok.is(tok::comma))
4300
      ConsumeToken();
4301

4302
    SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4303
    D.DeclIdent = II;
4304
    D.DeclIdentLoc = IdLoc;
4305
    D.Type = IteratorType;
4306
    D.AssignLoc = AssignLoc;
4307
    D.ColonLoc = ColonLoc;
4308
    D.SecColonLoc = SecColonLoc;
4309
    D.Range.Begin = Begin.get();
4310
    D.Range.End = End.get();
4311
    D.Range.Step = Step.get();
4312
  }
4313

4314
  // Parse ')'.
4315
  SourceLocation RLoc = Tok.getLocation();
4316
  if (!T.consumeClose())
4317
    RLoc = T.getCloseLocation();
4318

4319
  return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4320
                                               LLoc, RLoc, Data);
4321
}
4322

4323
bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind,
4324
                                        SemaOpenMP::OpenMPVarListDataTy &Data,
4325
                                        const LangOptions &LangOpts) {
4326
  // Currently the only reserved locator is 'omp_all_memory' which is only
4327
  // allowed on a depend clause.
4328
  if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4329
    return false;
4330

4331
  if (Tok.is(tok::identifier) &&
4332
      Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4333

4334
    if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4335
        Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4336
      Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4337
    else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4338
             Data.ExtraModifier != OMPC_DEPEND_inout)
4339
      Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4340
    else
4341
      Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4342
                               ? OMPC_DEPEND_outallmemory
4343
                               : OMPC_DEPEND_inoutallmemory;
4344
    ConsumeToken();
4345
    return true;
4346
  }
4347
  return false;
4348
}
4349

4350
/// Parse step size expression. Returns true if parsing is successfull,
4351
/// otherwise returns false.
4352
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data,
4353
                          OpenMPClauseKind CKind, SourceLocation ELoc) {
4354
  ExprResult Tail = P.ParseAssignmentExpression();
4355
  Sema &Actions = P.getActions();
4356
  Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4357
                                     /*DiscardedValue*/ false);
4358
  if (Tail.isUsable()) {
4359
    Data.DepModOrTailExpr = Tail.get();
4360
    Token CurTok = P.getCurToken();
4361
    if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
4362
      P.Diag(CurTok, diag::err_expected_punc) << "step expression";
4363
    }
4364
    return true;
4365
  }
4366
  return false;
4367
}
4368

4369
/// Parses clauses with list.
4370
bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
4371
                                OpenMPClauseKind Kind,
4372
                                SmallVectorImpl<Expr *> &Vars,
4373
                                SemaOpenMP::OpenMPVarListDataTy &Data) {
4374
  UnqualifiedId UnqualifiedReductionId;
4375
  bool InvalidReductionId = false;
4376
  bool IsInvalidMapperModifier = false;
4377

4378
  // Parse '('.
4379
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4380
  if (T.expectAndConsume(diag::err_expected_lparen_after,
4381
                         getOpenMPClauseName(Kind).data()))
4382
    return true;
4383

4384
  bool HasIterator = false;
4385
  bool InvalidIterator = false;
4386
  bool NeedRParenForLinear = false;
4387
  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4388
                                   tok::annot_pragma_openmp_end);
4389
  // Handle reduction-identifier for reduction clause.
4390
  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4391
      Kind == OMPC_in_reduction) {
4392
    Data.ExtraModifier = OMPC_REDUCTION_unknown;
4393
    if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4394
        (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
4395
        NextToken().is(tok::comma)) {
4396
      // Parse optional reduction modifier.
4397
      Data.ExtraModifier =
4398
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4399
      Data.ExtraModifierLoc = Tok.getLocation();
4400
      ConsumeToken();
4401
      assert(Tok.is(tok::comma) && "Expected comma.");
4402
      (void)ConsumeToken();
4403
    }
4404
    ColonProtectionRAIIObject ColonRAII(*this);
4405
    if (getLangOpts().CPlusPlus)
4406
      ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4407
                                     /*ObjectType=*/nullptr,
4408
                                     /*ObjectHasErrors=*/false,
4409
                                     /*EnteringContext=*/false);
4410
    InvalidReductionId = ParseReductionId(
4411
        *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4412
    if (InvalidReductionId) {
4413
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4414
                StopBeforeMatch);
4415
    }
4416
    if (Tok.is(tok::colon))
4417
      Data.ColonLoc = ConsumeToken();
4418
    else
4419
      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
4420
    if (!InvalidReductionId)
4421
      Data.ReductionOrMapperId =
4422
          Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
4423
  } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4424
    if (getLangOpts().OpenMP >= 50) {
4425
      if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4426
        // Handle optional dependence modifier.
4427
        // iterator(iterators-definition)
4428
        // where iterators-definition is iterator-specifier [,
4429
        // iterators-definition ]
4430
        // where iterator-specifier is [ iterator-type ] identifier =
4431
        // range-specification
4432
        HasIterator = true;
4433
        EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
4434
        ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4435
        Data.DepModOrTailExpr = IteratorRes.get();
4436
        // Parse ','
4437
        ExpectAndConsume(tok::comma);
4438
      }
4439
    }
4440
    // Handle dependency type for depend clause.
4441
    ColonProtectionRAIIObject ColonRAII(*this);
4442
    Data.ExtraModifier = getOpenMPSimpleClauseType(
4443
        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4444
        getLangOpts());
4445
    Data.ExtraModifierLoc = Tok.getLocation();
4446
    if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
4447
        (Kind == OMPC_doacross &&
4448
         Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
4449
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4450
                StopBeforeMatch);
4451
    } else {
4452
      ConsumeToken();
4453
      // Special processing for depend(source) clause.
4454
      if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4455
          Data.ExtraModifier == OMPC_DEPEND_source) {
4456
        // Parse ')'.
4457
        T.consumeClose();
4458
        return false;
4459
      }
4460
    }
4461
    if (Tok.is(tok::colon)) {
4462
      Data.ColonLoc = ConsumeToken();
4463
    } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
4464
      Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4465
                                      : diag::warn_pragma_expected_colon)
4466
          << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
4467
    }
4468
    if (Kind == OMPC_doacross) {
4469
      if (Tok.is(tok::identifier) &&
4470
          Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
4471
        Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
4472
                                 ? OMPC_DOACROSS_source_omp_cur_iteration
4473
                                 : OMPC_DOACROSS_sink_omp_cur_iteration;
4474
        ConsumeToken();
4475
      }
4476
      if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
4477
        if (Tok.isNot(tok::minus)) {
4478
          Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4479
              << getOpenMPClauseName(Kind) << 0 << 0;
4480
          SkipUntil(tok::r_paren);
4481
          return false;
4482
        } else {
4483
          ConsumeToken();
4484
          SourceLocation Loc = Tok.getLocation();
4485
          uint64_t Value = 0;
4486
          if (Tok.isNot(tok::numeric_constant) ||
4487
              (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
4488
            Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
4489
                << getOpenMPClauseName(Kind) << 0 << 0;
4490
            SkipUntil(tok::r_paren);
4491
            return false;
4492
          }
4493
        }
4494
      }
4495
      if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
4496
        if (Tok.isNot(tok::r_paren)) {
4497
          Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4498
              << getOpenMPClauseName(Kind) << 1 << 1;
4499
          SkipUntil(tok::r_paren);
4500
          return false;
4501
        }
4502
      }
4503
      // Only the 'sink' case has the expression list.
4504
      if (Kind == OMPC_doacross &&
4505
          (Data.ExtraModifier == OMPC_DOACROSS_source ||
4506
           Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
4507
           Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
4508
        // Parse ')'.
4509
        T.consumeClose();
4510
        return false;
4511
      }
4512
    }
4513
  } else if (Kind == OMPC_linear) {
4514
    // Try to parse modifier if any.
4515
    Data.ExtraModifier = OMPC_LINEAR_val;
4516
    if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
4517
      Data.ExtraModifier =
4518
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4519
      Data.ExtraModifierLoc = ConsumeToken();
4520
      LinearT.consumeOpen();
4521
      NeedRParenForLinear = true;
4522
      if (getLangOpts().OpenMP >= 52)
4523
        Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
4524
            << "linear-modifier(list)" << getOpenMPClauseName(Kind)
4525
            << "linear(list: [linear-modifier,] step(step-size))";
4526
    }
4527
  } else if (Kind == OMPC_lastprivate) {
4528
    // Try to parse modifier if any.
4529
    Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
4530
    // Conditional modifier allowed only in OpenMP 5.0 and not supported in
4531
    // distribute and taskloop based directives.
4532
    if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
4533
         !isOpenMPTaskLoopDirective(DKind)) &&
4534
        Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
4535
      Data.ExtraModifier =
4536
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4537
      Data.ExtraModifierLoc = Tok.getLocation();
4538
      ConsumeToken();
4539
      assert(Tok.is(tok::colon) && "Expected colon.");
4540
      Data.ColonLoc = ConsumeToken();
4541
    }
4542
  } else if (Kind == OMPC_map) {
4543
    // Handle optional iterator map modifier.
4544
    if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4545
      HasIterator = true;
4546
      EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
4547
      Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4548
      Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4549
      ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4550
      Data.IteratorExpr = IteratorRes.get();
4551
      // Parse ','
4552
      ExpectAndConsume(tok::comma);
4553
      if (getLangOpts().OpenMP < 52) {
4554
        Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4555
            << (getLangOpts().OpenMP >= 51 ? 1 : 0)
4556
            << getLangOpts().OpenMPExtensions;
4557
        InvalidIterator = true;
4558
      }
4559
    }
4560
    // Handle map type for map clause.
4561
    ColonProtectionRAIIObject ColonRAII(*this);
4562

4563
    // The first identifier may be a list item, a map-type or a
4564
    // map-type-modifier. The map-type can also be delete which has the same
4565
    // spelling of the C++ delete keyword.
4566
    Data.ExtraModifier = OMPC_MAP_unknown;
4567
    Data.ExtraModifierLoc = Tok.getLocation();
4568

4569
    // Check for presence of a colon in the map clause.
4570
    TentativeParsingAction TPA(*this);
4571
    bool ColonPresent = false;
4572
    if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4573
                  StopBeforeMatch)) {
4574
      if (Tok.is(tok::colon))
4575
        ColonPresent = true;
4576
    }
4577
    TPA.Revert();
4578
    // Only parse map-type-modifier[s] and map-type if a colon is present in
4579
    // the map clause.
4580
    if (ColonPresent) {
4581
      if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
4582
        Diag(Tok, diag::err_omp_map_modifier_specification_list);
4583
      IsInvalidMapperModifier = parseMapTypeModifiers(Data);
4584
      if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
4585
        parseMapType(*this, Data);
4586
      else
4587
        SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
4588
    }
4589
    if (Data.ExtraModifier == OMPC_MAP_unknown) {
4590
      Data.ExtraModifier = OMPC_MAP_tofrom;
4591
      if (getLangOpts().OpenMP >= 52) {
4592
        if (DKind == OMPD_target_enter_data)
4593
          Data.ExtraModifier = OMPC_MAP_to;
4594
        else if (DKind == OMPD_target_exit_data)
4595
          Data.ExtraModifier = OMPC_MAP_from;
4596
      }
4597
      Data.IsMapTypeImplicit = true;
4598
    }
4599

4600
    if (Tok.is(tok::colon))
4601
      Data.ColonLoc = ConsumeToken();
4602
  } else if (Kind == OMPC_to || Kind == OMPC_from) {
4603
    while (Tok.is(tok::identifier)) {
4604
      auto Modifier = static_cast<OpenMPMotionModifierKind>(
4605
          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
4606
      if (Modifier == OMPC_MOTION_MODIFIER_unknown)
4607
        break;
4608
      Data.MotionModifiers.push_back(Modifier);
4609
      Data.MotionModifiersLoc.push_back(Tok.getLocation());
4610
      ConsumeToken();
4611
      if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
4612
        IsInvalidMapperModifier = parseMapperModifier(Data);
4613
        if (IsInvalidMapperModifier)
4614
          break;
4615
      }
4616
      // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
4617
      if (getLangOpts().OpenMP < 51)
4618
        break;
4619
      // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
4620
      // TODO: Is that intentional?
4621
      if (Tok.is(tok::comma))
4622
        ConsumeToken();
4623
    }
4624
    if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
4625
      if (!IsInvalidMapperModifier) {
4626
        if (getLangOpts().OpenMP < 51)
4627
          Diag(Tok, diag::warn_pragma_expected_colon) << ")";
4628
        else
4629
          Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
4630
      }
4631
      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4632
                StopBeforeMatch);
4633
    }
4634
    // OpenMP 5.1 permits a ':' even without a preceding modifier.  TODO: Is
4635
    // that intentional?
4636
    if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
4637
        Tok.is(tok::colon))
4638
      Data.ColonLoc = ConsumeToken();
4639
  } else if (Kind == OMPC_allocate ||
4640
             (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
4641
              PP.getSpelling(Tok) == "iterator")) {
4642
    // Handle optional allocator expression followed by colon delimiter.
4643
    ColonProtectionRAIIObject ColonRAII(*this);
4644
    TentativeParsingAction TPA(*this);
4645
    // OpenMP 5.0, 2.10.1, task Construct.
4646
    // where aff-modifier is one of the following:
4647
    // iterator(iterators-definition)
4648
    ExprResult Tail;
4649
    if (Kind == OMPC_allocate) {
4650
      Tail = ParseAssignmentExpression();
4651
    } else {
4652
      HasIterator = true;
4653
      EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
4654
      Tail = ParseOpenMPIteratorsExpr();
4655
    }
4656
    Tail = Actions.CorrectDelayedTyposInExpr(Tail);
4657
    Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
4658
                                       /*DiscardedValue=*/false);
4659
    if (Tail.isUsable()) {
4660
      if (Tok.is(tok::colon)) {
4661
        Data.DepModOrTailExpr = Tail.get();
4662
        Data.ColonLoc = ConsumeToken();
4663
        TPA.Commit();
4664
      } else {
4665
        // Colon not found, parse only list of variables.
4666
        TPA.Revert();
4667
      }
4668
    } else {
4669
      // Parsing was unsuccessfull, revert and skip to the end of clause or
4670
      // directive.
4671
      TPA.Revert();
4672
      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4673
                StopBeforeMatch);
4674
    }
4675
  } else if (Kind == OMPC_adjust_args) {
4676
    // Handle adjust-op for adjust_args clause.
4677
    ColonProtectionRAIIObject ColonRAII(*this);
4678
    Data.ExtraModifier = getOpenMPSimpleClauseType(
4679
        Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4680
        getLangOpts());
4681
    Data.ExtraModifierLoc = Tok.getLocation();
4682
    if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
4683
      Diag(Tok, diag::err_omp_unknown_adjust_args_op);
4684
      SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
4685
    } else {
4686
      ConsumeToken();
4687
      if (Tok.is(tok::colon))
4688
        Data.ColonLoc = Tok.getLocation();
4689
      ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
4690
                       "adjust-op");
4691
    }
4692
  }
4693

4694
  bool IsComma =
4695
      (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
4696
       Kind != OMPC_in_reduction && Kind != OMPC_depend &&
4697
       Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
4698
      (Kind == OMPC_reduction && !InvalidReductionId) ||
4699
      (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
4700
      (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
4701
      (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
4702
      (Kind == OMPC_adjust_args &&
4703
       Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
4704
  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
4705
  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
4706
                     Tok.isNot(tok::annot_pragma_openmp_end))) {
4707
    ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
4708
    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
4709
    if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) {
4710
      // Parse variable
4711
      ExprResult VarExpr =
4712
          Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
4713
      if (VarExpr.isUsable()) {
4714
        Vars.push_back(VarExpr.get());
4715
      } else {
4716
        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4717
                  StopBeforeMatch);
4718
      }
4719
    }
4720
    // Skip ',' if any
4721
    IsComma = Tok.is(tok::comma);
4722
    if (IsComma)
4723
      ConsumeToken();
4724
    else if (Tok.isNot(tok::r_paren) &&
4725
             Tok.isNot(tok::annot_pragma_openmp_end) &&
4726
             (!MayHaveTail || Tok.isNot(tok::colon)))
4727
      Diag(Tok, diag::err_omp_expected_punc)
4728
          << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
4729
                                   : getOpenMPClauseName(Kind))
4730
          << (Kind == OMPC_flush);
4731
  }
4732

4733
  // Parse ')' for linear clause with modifier.
4734
  if (NeedRParenForLinear)
4735
    LinearT.consumeClose();
4736

4737
  // Parse ':' linear modifiers (val, uval, ref or step(step-size))
4738
  // or parse ':' alignment.
4739
  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
4740
  bool StepFound = false;
4741
  bool ModifierFound = false;
4742
  if (MustHaveTail) {
4743
    Data.ColonLoc = Tok.getLocation();
4744
    SourceLocation ELoc = ConsumeToken();
4745

4746
    if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
4747
      while (Tok.isNot(tok::r_paren)) {
4748
        if (Tok.is(tok::identifier)) {
4749
          // identifier could be a linear kind (val, uval, ref) or step
4750
          // modifier or step size
4751
          OpenMPLinearClauseKind LinKind =
4752
              static_cast<OpenMPLinearClauseKind>(getOpenMPSimpleClauseType(
4753
                  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4754
                  getLangOpts()));
4755

4756
          if (LinKind == OMPC_LINEAR_step) {
4757
            if (StepFound)
4758
              Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
4759

4760
            BalancedDelimiterTracker StepT(*this, tok::l_paren,
4761
                                           tok::annot_pragma_openmp_end);
4762
            SourceLocation StepModifierLoc = ConsumeToken();
4763
            // parse '('
4764
            if (StepT.consumeOpen())
4765
              Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
4766

4767
            // parse step size expression
4768
            StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4769
            if (StepFound)
4770
              Data.StepModifierLoc = StepModifierLoc;
4771

4772
            // parse ')'
4773
            StepT.consumeClose();
4774
          } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
4775
            if (ModifierFound)
4776
              Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
4777

4778
            Data.ExtraModifier = LinKind;
4779
            Data.ExtraModifierLoc = ConsumeToken();
4780
            ModifierFound = true;
4781
          } else {
4782
            StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4783
          }
4784
        } else {
4785
          // parse an integer expression as step size
4786
          StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4787
        }
4788

4789
        if (Tok.is(tok::comma))
4790
          ConsumeToken();
4791
        if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
4792
          break;
4793
      }
4794
      if (!StepFound && !ModifierFound)
4795
        Diag(ELoc, diag::err_expected_expression);
4796
    } else {
4797
      // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
4798
      ExprResult Tail = ParseAssignmentExpression();
4799
      Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4800
                                         /*DiscardedValue*/ false);
4801
      if (Tail.isUsable())
4802
        Data.DepModOrTailExpr = Tail.get();
4803
      else
4804
        SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4805
                  StopBeforeMatch);
4806
    }
4807
  }
4808

4809
  // Parse ')'.
4810
  Data.RLoc = Tok.getLocation();
4811
  if (!T.consumeClose())
4812
    Data.RLoc = T.getCloseLocation();
4813
  // Exit from scope when the iterator is used in depend clause.
4814
  if (HasIterator)
4815
    ExitScope();
4816
  return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
4817
          Vars.empty()) ||
4818
         (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
4819
         InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
4820
}
4821

4822
/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
4823
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
4824
/// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
4825
///
4826
///    private-clause:
4827
///       'private' '(' list ')'
4828
///    firstprivate-clause:
4829
///       'firstprivate' '(' list ')'
4830
///    lastprivate-clause:
4831
///       'lastprivate' '(' list ')'
4832
///    shared-clause:
4833
///       'shared' '(' list ')'
4834
///    linear-clause:
4835
///       'linear' '(' linear-list [ ':' linear-step ] ')'
4836
///    aligned-clause:
4837
///       'aligned' '(' list [ ':' alignment ] ')'
4838
///    reduction-clause:
4839
///       'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
4840
///    task_reduction-clause:
4841
///       'task_reduction' '(' reduction-identifier ':' list ')'
4842
///    in_reduction-clause:
4843
///       'in_reduction' '(' reduction-identifier ':' list ')'
4844
///    copyprivate-clause:
4845
///       'copyprivate' '(' list ')'
4846
///    flush-clause:
4847
///       'flush' '(' list ')'
4848
///    depend-clause:
4849
///       'depend' '(' in | out | inout : list | source ')'
4850
///    map-clause:
4851
///       'map' '(' [ [ always [,] ] [ close [,] ]
4852
///          [ mapper '(' mapper-identifier ')' [,] ]
4853
///          to | from | tofrom | alloc | release | delete ':' ] list ')';
4854
///    to-clause:
4855
///       'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
4856
///    from-clause:
4857
///       'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
4858
///    use_device_ptr-clause:
4859
///       'use_device_ptr' '(' list ')'
4860
///    use_device_addr-clause:
4861
///       'use_device_addr' '(' list ')'
4862
///    is_device_ptr-clause:
4863
///       'is_device_ptr' '(' list ')'
4864
///    has_device_addr-clause:
4865
///       'has_device_addr' '(' list ')'
4866
///    allocate-clause:
4867
///       'allocate' '(' [ allocator ':' ] list ')'
4868
///    nontemporal-clause:
4869
///       'nontemporal' '(' list ')'
4870
///    inclusive-clause:
4871
///       'inclusive' '(' list ')'
4872
///    exclusive-clause:
4873
///       'exclusive' '(' list ')'
4874
///
4875
/// For 'linear' clause linear-list may have the following forms:
4876
///  list
4877
///  modifier(list)
4878
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
4879
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
4880
                                            OpenMPClauseKind Kind,
4881
                                            bool ParseOnly) {
4882
  SourceLocation Loc = Tok.getLocation();
4883
  SourceLocation LOpen = ConsumeToken();
4884
  SmallVector<Expr *, 4> Vars;
4885
  SemaOpenMP::OpenMPVarListDataTy Data;
4886

4887
  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
4888
    return nullptr;
4889

4890
  if (ParseOnly)
4891
    return nullptr;
4892
  OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
4893
  return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
4894
}
4895

4896
bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
4897
                                       SourceLocation &ClauseNameLoc,
4898
                                       SourceLocation &OpenLoc,
4899
                                       SourceLocation &CloseLoc,
4900
                                       SmallVectorImpl<Expr *> &Exprs,
4901
                                       bool ReqIntConst) {
4902
  assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
4903
         "Expected parsing to start at clause name");
4904
  ClauseNameLoc = ConsumeToken();
4905

4906
  // Parse inside of '(' and ')'.
4907
  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4908
  if (T.consumeOpen()) {
4909
    Diag(Tok, diag::err_expected) << tok::l_paren;
4910
    return true;
4911
  }
4912

4913
  // Parse the list with interleaved commas.
4914
  do {
4915
    ExprResult Val =
4916
        ReqIntConst ? ParseConstantExpression() : ParseAssignmentExpression();
4917
    if (!Val.isUsable()) {
4918
      // Encountered something other than an expression; abort to ')'.
4919
      T.skipToEnd();
4920
      return true;
4921
    }
4922
    Exprs.push_back(Val.get());
4923
  } while (TryConsumeToken(tok::comma));
4924

4925
  bool Result = T.consumeClose();
4926
  OpenLoc = T.getOpenLocation();
4927
  CloseLoc = T.getCloseLocation();
4928
  return Result;
4929
}
4930

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.