clang  20.0.0git
ParseOpenMP.cpp
Go to the documentation of this file.
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"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Basic/TokenKinds.h"
20 #include "clang/Parse/Parser.h"
23 #include "clang/Sema/Scope.h"
24 #include "clang/Sema/SemaAMDGPU.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;
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 
228  Token Tok = P.getCurToken();
229  Sema &Actions = P.getActions();
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,
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 ///
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 
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 
321  // Parse list of types until ':' token.
322  do {
323  ColonProtectionRAIIObject ColonRAII(*this);
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 |
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 |
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 
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 ///
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;
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 |
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.
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.
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;
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.
700  HasFunScope = true;
701  Scopes.Enter(Scope::FnScope | Scope::DeclScope |
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> ] ')' }
722  Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
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) {
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'.
802 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
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;
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 
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> ')' ':'.
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.
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();
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 =
1501  Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
1502  SourceRange(Loc, Tok.getLocation()));
1503 
1504  if (DeclVarData && !TI.Sets.empty())
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,
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())
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;
1787  SourceLocation LOpen;
1789  SourceLocation RLoc;
1790  SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
1792  : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1793 };
1794 } // anonymous namespace
1795 
1796 static std::optional<SimpleClauseData>
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());
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(
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;
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) {
1924  getCurScope(), SS, NameInfo);
1925  if (!ND)
1926  return;
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 
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)) {
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();
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: {
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())
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) {
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) {
2354  return nullptr;
2355  }
2356 
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  }
2371  ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2372  return nullptr;
2373  }
2374  case OMPD_assume: {
2375  Diag(Tok, diag::err_omp_unexpected_directive)
2376  << 1 << getOpenMPDirectiveName(DKind);
2377  break;
2378  }
2379  case OMPD_unknown:
2380  Diag(Tok, diag::err_omp_unknown_directive);
2381  break;
2382  default:
2383  switch (getDirectiveCategory(DKind)) {
2384  case Category::Executable:
2385  case Category::Meta:
2386  case Category::Subsidiary:
2387  case Category::Utility:
2388  Diag(Tok, diag::err_omp_unexpected_directive)
2389  << 1 << getOpenMPDirectiveName(DKind);
2390  break;
2391  case Category::Declarative:
2392  case Category::Informational:
2393  break;
2394  }
2395  }
2396  while (Tok.isNot(tok::annot_pragma_openmp_end))
2397  ConsumeAnyToken();
2398  ConsumeAnyToken();
2399  return nullptr;
2400 }
2401 
2402 StmtResult Parser::ParseOpenMPExecutableDirective(
2403  ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2404  bool ReadDirectiveWithinMetadirective) {
2405  assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive category");
2406 
2407  bool HasAssociatedStatement = true;
2408  Association Assoc = getDirectiveAssociation(DKind);
2409 
2410  // OMPD_ordered has None as association, but it comes in two variants,
2411  // the second of which is associated with a block.
2412  // OMPD_scan and OMPD_section are both "separating", but section is treated
2413  // as if it was associated with a statement, while scan is not.
2414  if (DKind != OMPD_ordered && DKind != OMPD_section &&
2415  (Assoc == Association::None || Assoc == Association::Separating)) {
2416  if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2417  ParsedStmtContext()) {
2418  Diag(Tok, diag::err_omp_immediate_directive)
2419  << getOpenMPDirectiveName(DKind) << 0;
2420  if (DKind == OMPD_error) {
2421  SkipUntil(tok::annot_pragma_openmp_end);
2422  return StmtError();
2423  }
2424  }
2425  HasAssociatedStatement = false;
2426  }
2427 
2428  SourceLocation EndLoc;
2430  llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2431  DeclarationNameInfo DirName;
2432  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
2433  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2435 
2436  // Special processing for flush and depobj clauses.
2437  Token ImplicitTok;
2438  bool ImplicitClauseAllowed = false;
2439  if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2440  ImplicitTok = Tok;
2441  ImplicitClauseAllowed = true;
2442  }
2443  ConsumeToken();
2444  // Parse directive name of the 'critical' directive if any.
2445  if (DKind == OMPD_critical) {
2446  BalancedDelimiterTracker T(*this, tok::l_paren,
2447  tok::annot_pragma_openmp_end);
2448  if (!T.consumeOpen()) {
2449  if (Tok.isAnyIdentifier()) {
2450  DirName =
2452  ConsumeAnyToken();
2453  } else {
2454  Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2455  }
2456  T.consumeClose();
2457  }
2458  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2459  CancelRegion = parseOpenMPDirectiveKind(*this);
2460  if (Tok.isNot(tok::annot_pragma_openmp_end))
2461  ConsumeToken();
2462  }
2463 
2464  if (isOpenMPLoopDirective(DKind))
2465  ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
2466  if (isOpenMPSimdDirective(DKind))
2467  ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
2468  ParseScope OMPDirectiveScope(this, ScopeFlags);
2469  Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2470  Loc);
2471 
2472  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2473  // If we are parsing for a directive within a metadirective, the directive
2474  // ends with a ')'.
2475  if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2476  while (Tok.isNot(tok::annot_pragma_openmp_end))
2477  ConsumeAnyToken();
2478  break;
2479  }
2480  bool HasImplicitClause = false;
2481  if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
2482  HasImplicitClause = true;
2483  // Push copy of the current token back to stream to properly parse
2484  // pseudo-clause OMPFlushClause or OMPDepobjClause.
2485  PP.EnterToken(Tok, /*IsReinject*/ true);
2486  PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
2487  ConsumeAnyToken();
2488  }
2489  OpenMPClauseKind CKind = Tok.isAnnotation()
2490  ? OMPC_unknown
2491  : getOpenMPClauseKind(PP.getSpelling(Tok));
2492  if (HasImplicitClause) {
2493  assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
2494  if (DKind == OMPD_flush) {
2495  CKind = OMPC_flush;
2496  } else {
2497  assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");
2498  CKind = OMPC_depobj;
2499  }
2500  }
2501  // No more implicit clauses allowed.
2502  ImplicitClauseAllowed = false;
2503  Actions.OpenMP().StartOpenMPClause(CKind);
2504  HasImplicitClause = false;
2505  OMPClause *Clause =
2506  ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2507  SeenClauses[unsigned(CKind)] = true;
2508  if (Clause)
2509  Clauses.push_back(Clause);
2510 
2511  // Skip ',' if any.
2512  if (Tok.is(tok::comma))
2513  ConsumeToken();
2514  Actions.OpenMP().EndOpenMPClause();
2515  }
2516  // End location of the directive.
2517  EndLoc = Tok.getLocation();
2518  // Consume final annot_pragma_openmp_end.
2519  ConsumeAnnotationToken();
2520 
2521  if (DKind == OMPD_ordered) {
2522  // If the depend or doacross clause is specified, the ordered construct
2523  // is a stand-alone directive.
2524  for (auto CK : {OMPC_depend, OMPC_doacross}) {
2525  if (SeenClauses[unsigned(CK)]) {
2526  if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2527  ParsedStmtContext()) {
2528  Diag(Loc, diag::err_omp_immediate_directive)
2529  << getOpenMPDirectiveName(DKind) << 1 << getOpenMPClauseName(CK);
2530  }
2531  HasAssociatedStatement = false;
2532  }
2533  }
2534  }
2535 
2536  if (DKind == OMPD_tile && !SeenClauses[unsigned(OMPC_sizes)]) {
2537  Diag(Loc, diag::err_omp_required_clause)
2538  << getOpenMPDirectiveName(OMPD_tile) << "sizes";
2539  }
2540 
2541  StmtResult AssociatedStmt;
2542  if (HasAssociatedStatement) {
2543  // The body is a block scope like in Lambdas and Blocks.
2544  Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2545  // FIXME: We create a bogus CompoundStmt scope to hold the contents of
2546  // the captured region. Code elsewhere assumes that any FunctionScopeInfo
2547  // should have at least one compound statement scope within it.
2548  ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2549  {
2550  Sema::CompoundScopeRAII Scope(Actions);
2551  AssociatedStmt = ParseStatement();
2552 
2553  if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) &&
2554  getLangOpts().OpenMPIRBuilder)
2555  AssociatedStmt =
2556  Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());
2557  }
2558  AssociatedStmt =
2559  Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2560  } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2561  DKind == OMPD_target_exit_data) {
2562  Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2563  AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
2564  Actions.ActOnCompoundStmt(Loc, Loc, std::nullopt,
2565  /*isStmtExpr=*/false));
2566  AssociatedStmt =
2567  Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2568  }
2569 
2571  DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2572 
2573  // Exit scope.
2574  Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2575  OMPDirectiveScope.Exit();
2576 
2577  return Directive;
2578 }
2579 
2580 StmtResult Parser::ParseOpenMPInformationalDirective(
2581  ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
2582  bool ReadDirectiveWithinMetadirective) {
2583  assert(isOpenMPInformationalDirective(DKind) &&
2584  "Unexpected directive category");
2585 
2586  bool HasAssociatedStatement = true;
2587 
2589  llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2590  DeclarationNameInfo DirName;
2591  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
2593  ParseScope OMPDirectiveScope(this, ScopeFlags);
2594 
2595  Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
2596  Loc);
2597 
2598  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2599  if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
2600  while (Tok.isNot(tok::annot_pragma_openmp_end))
2601  ConsumeAnyToken();
2602  break;
2603  }
2604 
2605  OpenMPClauseKind CKind = Tok.isAnnotation()
2606  ? OMPC_unknown
2607  : getOpenMPClauseKind(PP.getSpelling(Tok));
2608  Actions.OpenMP().StartOpenMPClause(CKind);
2609  OMPClause *Clause =
2610  ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
2611  SeenClauses[unsigned(CKind)] = true;
2612  if (Clause)
2613  Clauses.push_back(Clause);
2614 
2615  if (Tok.is(tok::comma))
2616  ConsumeToken();
2617  Actions.OpenMP().EndOpenMPClause();
2618  }
2619 
2620  SourceLocation EndLoc = Tok.getLocation();
2621  ConsumeAnnotationToken();
2622 
2623  StmtResult AssociatedStmt;
2624  if (HasAssociatedStatement) {
2625  Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
2626  ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2627  {
2628  Sema::CompoundScopeRAII Scope(Actions);
2629  AssociatedStmt = ParseStatement();
2630  }
2631  AssociatedStmt =
2632  Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
2633  }
2634 
2636  DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
2637 
2638  Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
2639  OMPDirectiveScope.Exit();
2640 
2641  return Directive;
2642 }
2643 
2644 /// Parsing of declarative or executable OpenMP directives.
2645 ///
2646 /// threadprivate-directive:
2647 /// annot_pragma_openmp 'threadprivate' simple-variable-list
2648 /// annot_pragma_openmp_end
2649 ///
2650 /// allocate-directive:
2651 /// annot_pragma_openmp 'allocate' simple-variable-list
2652 /// annot_pragma_openmp_end
2653 ///
2654 /// declare-reduction-directive:
2655 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
2656 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
2657 /// ('omp_priv' '=' <expression>|<function_call>) ')']
2658 /// annot_pragma_openmp_end
2659 ///
2660 /// declare-mapper-directive:
2661 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
2662 /// <type> <var> ')' [<clause>[[,] <clause>] ... ]
2663 /// annot_pragma_openmp_end
2664 ///
2665 /// executable-directive:
2666 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
2667 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
2668 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
2669 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error'
2670 /// | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
2671 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
2672 /// 'master taskloop' | 'master taskloop simd' | 'parallel master
2673 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
2674 /// enter data' | 'target exit data' | 'target parallel' | 'target
2675 /// parallel for' | 'target update' | 'distribute parallel for' |
2676 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel
2677 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute
2678 /// simd' | 'teams distribute parallel for simd' | 'teams distribute
2679 /// parallel for' | 'target teams' | 'target teams distribute' | 'target
2680 /// teams distribute parallel for' | 'target teams distribute parallel
2681 /// for simd' | 'target teams distribute simd' | 'masked' |
2682 /// 'parallel masked' {clause} annot_pragma_openmp_end
2683 ///
2684 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2685  ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {
2686  if (!ReadDirectiveWithinMetadirective)
2687  assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2688  "Not an OpenMP directive!");
2689  ParsingOpenMPDirectiveRAII DirScope(*this);
2690  ParenBraceBracketBalancer BalancerRAIIObj(*this);
2691  SourceLocation Loc = ReadDirectiveWithinMetadirective
2692  ? Tok.getLocation()
2693  : ConsumeAnnotationToken();
2695  if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2696  Diag(Tok, diag::err_omp_unknown_directive);
2697  return StmtError();
2698  }
2699 
2701 
2702  bool IsExecutable = [&]() {
2703  if (DKind == OMPD_error) // OMPD_error is handled as executable
2704  return true;
2705  auto Res = getDirectiveCategory(DKind);
2706  return Res == Category::Executable || Res == Category::Subsidiary;
2707  }();
2708 
2709  if (IsExecutable) {
2710  Directive = ParseOpenMPExecutableDirective(
2711  StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2712  assert(!Directive.isUnset() && "Executable directive remained unprocessed");
2713  return Directive;
2714  }
2715 
2716  switch (DKind) {
2717  case OMPD_nothing:
2718  ConsumeToken();
2719  // If we are parsing the directive within a metadirective, the directive
2720  // ends with a ')'.
2721  if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))
2722  while (Tok.isNot(tok::annot_pragma_openmp_end))
2723  ConsumeAnyToken();
2724  else
2725  skipUntilPragmaOpenMPEnd(DKind);
2726  if (Tok.is(tok::annot_pragma_openmp_end))
2727  ConsumeAnnotationToken();
2728  // return an empty statement
2729  return StmtEmpty();
2730  case OMPD_metadirective: {
2731  ConsumeToken();
2733 
2734  // First iteration of parsing all clauses of metadirective.
2735  // This iteration only parses and collects all context selector ignoring the
2736  // associated directives.
2737  TentativeParsingAction TPA(*this);
2738  ASTContext &ASTContext = Actions.getASTContext();
2739 
2740  BalancedDelimiterTracker T(*this, tok::l_paren,
2741  tok::annot_pragma_openmp_end);
2742  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2743  OpenMPClauseKind CKind = Tok.isAnnotation()
2744  ? OMPC_unknown
2745  : getOpenMPClauseKind(PP.getSpelling(Tok));
2746  SourceLocation Loc = ConsumeToken();
2747 
2748  // Parse '('.
2749  if (T.expectAndConsume(diag::err_expected_lparen_after,
2750  getOpenMPClauseName(CKind).data()))
2751  return Directive;
2752 
2753  OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2754  if (CKind == OMPC_when) {
2755  // parse and get OMPTraitInfo to pass to the When clause
2756  parseOMPContextSelectors(Loc, TI);
2757  if (TI.Sets.size() == 0) {
2758  Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";
2759  TPA.Commit();
2760  return Directive;
2761  }
2762 
2763  // Parse ':'
2764  if (Tok.is(tok::colon))
2765  ConsumeAnyToken();
2766  else {
2767  Diag(Tok, diag::err_omp_expected_colon) << "when clause";
2768  TPA.Commit();
2769  return Directive;
2770  }
2771  }
2772  // Skip Directive for now. We will parse directive in the second iteration
2773  int paren = 0;
2774  while (Tok.isNot(tok::r_paren) || paren != 0) {
2775  if (Tok.is(tok::l_paren))
2776  paren++;
2777  if (Tok.is(tok::r_paren))
2778  paren--;
2779  if (Tok.is(tok::annot_pragma_openmp_end)) {
2780  Diag(Tok, diag::err_omp_expected_punc)
2781  << getOpenMPClauseName(CKind) << 0;
2782  TPA.Commit();
2783  return Directive;
2784  }
2785  ConsumeAnyToken();
2786  }
2787  // Parse ')'
2788  if (Tok.is(tok::r_paren))
2789  T.consumeClose();
2790 
2791  VariantMatchInfo VMI;
2793 
2794  VMIs.push_back(VMI);
2795  }
2796 
2797  TPA.Revert();
2798  // End of the first iteration. Parser is reset to the start of metadirective
2799 
2800  std::function<void(StringRef)> DiagUnknownTrait =
2801  [this, Loc](StringRef ISATrait) {
2802  // TODO Track the selector locations in a way that is accessible here
2803  // to improve the diagnostic location.
2804  Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2805  };
2806  TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),
2807  /* CurrentFunctionDecl */ nullptr,
2809 
2810  // A single match is returned for OpenMP 5.0
2811  int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2812 
2813  int Idx = 0;
2814  // In OpenMP 5.0 metadirective is either replaced by another directive or
2815  // ignored.
2816  // TODO: In OpenMP 5.1 generate multiple directives based upon the matches
2817  // found by getBestWhenMatchForContext.
2818  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2819  // OpenMP 5.0 implementation - Skip to the best index found.
2820  if (Idx++ != BestIdx) {
2821  ConsumeToken(); // Consume clause name
2822  T.consumeOpen(); // Consume '('
2823  int paren = 0;
2824  // Skip everything inside the clause
2825  while (Tok.isNot(tok::r_paren) || paren != 0) {
2826  if (Tok.is(tok::l_paren))
2827  paren++;
2828  if (Tok.is(tok::r_paren))
2829  paren--;
2830  ConsumeAnyToken();
2831  }
2832  // Parse ')'
2833  if (Tok.is(tok::r_paren))
2834  T.consumeClose();
2835  continue;
2836  }
2837 
2838  OpenMPClauseKind CKind = Tok.isAnnotation()
2839  ? OMPC_unknown
2840  : getOpenMPClauseKind(PP.getSpelling(Tok));
2841  SourceLocation Loc = ConsumeToken();
2842 
2843  // Parse '('.
2844  T.consumeOpen();
2845 
2846  // Skip ContextSelectors for when clause
2847  if (CKind == OMPC_when) {
2848  OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
2849  // parse and skip the ContextSelectors
2850  parseOMPContextSelectors(Loc, TI);
2851 
2852  // Parse ':'
2853  ConsumeAnyToken();
2854  }
2855 
2856  // If no directive is passed, skip in OpenMP 5.0.
2857  // TODO: Generate nothing directive from OpenMP 5.1.
2858  if (Tok.is(tok::r_paren)) {
2859  SkipUntil(tok::annot_pragma_openmp_end);
2860  break;
2861  }
2862 
2863  // Parse Directive
2864  Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2865  StmtCtx,
2866  /*ReadDirectiveWithinMetadirective=*/true);
2867  break;
2868  }
2869  break;
2870  }
2871  case OMPD_threadprivate: {
2872  // FIXME: Should this be permitted in C++?
2873  if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2874  ParsedStmtContext()) {
2875  Diag(Tok, diag::err_omp_immediate_directive)
2876  << getOpenMPDirectiveName(DKind) << 0;
2877  }
2878  ConsumeToken();
2879  DeclDirectiveListParserHelper Helper(this, DKind);
2880  if (!ParseOpenMPSimpleVarList(DKind, Helper,
2881  /*AllowScopeSpecifier=*/false)) {
2882  skipUntilPragmaOpenMPEnd(DKind);
2883  DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(
2884  Loc, Helper.getIdentifiers());
2885  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2886  }
2887  SkipUntil(tok::annot_pragma_openmp_end);
2888  break;
2889  }
2890  case OMPD_allocate: {
2891  // FIXME: Should this be permitted in C++?
2892  if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2893  ParsedStmtContext()) {
2894  Diag(Tok, diag::err_omp_immediate_directive)
2895  << getOpenMPDirectiveName(DKind) << 0;
2896  }
2897  ConsumeToken();
2898  DeclDirectiveListParserHelper Helper(this, DKind);
2899  if (!ParseOpenMPSimpleVarList(DKind, Helper,
2900  /*AllowScopeSpecifier=*/false)) {
2902  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
2903  llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
2904  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
2905  OpenMPClauseKind CKind =
2906  Tok.isAnnotation() ? OMPC_unknown
2907  : getOpenMPClauseKind(PP.getSpelling(Tok));
2908  Actions.OpenMP().StartOpenMPClause(CKind);
2909  OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
2910  !SeenClauses[unsigned(CKind)]);
2911  SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2912  StopBeforeMatch);
2913  SeenClauses[unsigned(CKind)] = true;
2914  if (Clause != nullptr)
2915  Clauses.push_back(Clause);
2916  if (Tok.is(tok::annot_pragma_openmp_end)) {
2917  Actions.OpenMP().EndOpenMPClause();
2918  break;
2919  }
2920  // Skip ',' if any.
2921  if (Tok.is(tok::comma))
2922  ConsumeToken();
2923  Actions.OpenMP().EndOpenMPClause();
2924  }
2925  skipUntilPragmaOpenMPEnd(DKind);
2926  }
2927  DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(
2928  Loc, Helper.getIdentifiers(), Clauses);
2929  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2930  }
2931  SkipUntil(tok::annot_pragma_openmp_end);
2932  break;
2933  }
2934  case OMPD_declare_reduction:
2935  ConsumeToken();
2936  if (DeclGroupPtrTy Res =
2937  ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
2938  skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2939  ConsumeAnyToken();
2940  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2941  } else {
2942  SkipUntil(tok::annot_pragma_openmp_end);
2943  }
2944  break;
2945  case OMPD_declare_mapper: {
2946  ConsumeToken();
2947  if (DeclGroupPtrTy Res =
2948  ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
2949  // Skip the last annot_pragma_openmp_end.
2950  ConsumeAnnotationToken();
2951  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
2952  } else {
2953  SkipUntil(tok::annot_pragma_openmp_end);
2954  }
2955  break;
2956  }
2957  case OMPD_reverse:
2958  case OMPD_interchange:
2959  case OMPD_declare_target: {
2960  SourceLocation DTLoc = ConsumeAnyToken();
2961  bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
2962  SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2963  if (HasClauses)
2964  ParseOMPDeclareTargetClauses(DTCI);
2965  bool HasImplicitMappings =
2966  !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2967 
2968  if (HasImplicitMappings) {
2969  Diag(Tok, diag::err_omp_unexpected_directive)
2970  << 1 << getOpenMPDirectiveName(DKind);
2971  SkipUntil(tok::annot_pragma_openmp_end);
2972  break;
2973  }
2974 
2975  // Skip the last annot_pragma_openmp_end.
2976  ConsumeAnyToken();
2977 
2979  break;
2980  }
2981  case OMPD_declare_simd:
2982  case OMPD_begin_declare_target:
2983  case OMPD_end_declare_target:
2984  case OMPD_requires:
2985  case OMPD_begin_declare_variant:
2986  case OMPD_end_declare_variant:
2987  case OMPD_declare_variant:
2988  Diag(Tok, diag::err_omp_unexpected_directive)
2989  << 1 << getOpenMPDirectiveName(DKind);
2990  SkipUntil(tok::annot_pragma_openmp_end);
2991  break;
2992  case OMPD_assume: {
2993  ConsumeToken();
2994  Directive = ParseOpenMPInformationalDirective(
2995  StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
2996  assert(!Directive.isUnset() &&
2997  "Informational directive remains unprocessed");
2998  return Directive;
2999  }
3000  case OMPD_unknown:
3001  default:
3002  Diag(Tok, diag::err_omp_unknown_directive);
3003  SkipUntil(tok::annot_pragma_openmp_end);
3004  break;
3005  }
3006  return Directive;
3007 }
3008 
3009 // Parses simple list:
3010 // simple-variable-list:
3011 // '(' id-expression {, id-expression} ')'
3012 //
3013 bool Parser::ParseOpenMPSimpleVarList(
3015  const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
3016  &Callback,
3017  bool AllowScopeSpecifier) {
3018  // Parse '('.
3019  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3020  if (T.expectAndConsume(diag::err_expected_lparen_after,
3021  getOpenMPDirectiveName(Kind).data()))
3022  return true;
3023  bool IsCorrect = true;
3024  bool NoIdentIsFound = true;
3025 
3026  // Read tokens while ')' or annot_pragma_openmp_end is not found.
3027  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
3028  CXXScopeSpec SS;
3029  UnqualifiedId Name;
3030  // Read var name.
3031  Token PrevTok = Tok;
3032  NoIdentIsFound = false;
3033 
3034  if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
3035  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
3036  /*ObjectHasErrors=*/false, false)) {
3037  IsCorrect = false;
3038  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3039  StopBeforeMatch);
3040  } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
3041  /*ObjectHadErrors=*/false, false, false,
3042  false, false, nullptr, Name)) {
3043  IsCorrect = false;
3044  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3045  StopBeforeMatch);
3046  } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
3047  Tok.isNot(tok::annot_pragma_openmp_end)) {
3048  IsCorrect = false;
3049  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3050  StopBeforeMatch);
3051  Diag(PrevTok.getLocation(), diag::err_expected)
3052  << tok::identifier
3053  << SourceRange(PrevTok.getLocation(), PrevTokLocation);
3054  } else {
3055  Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
3056  }
3057  // Consume ','.
3058  if (Tok.is(tok::comma)) {
3059  ConsumeToken();
3060  }
3061  }
3062 
3063  if (NoIdentIsFound) {
3064  Diag(Tok, diag::err_expected) << tok::identifier;
3065  IsCorrect = false;
3066  }
3067 
3068  // Parse ')'.
3069  IsCorrect = !T.consumeClose() && IsCorrect;
3070 
3071  return !IsCorrect;
3072 }
3073 
3074 OMPClause *Parser::ParseOpenMPSizesClause() {
3075  SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
3076  SmallVector<Expr *, 4> ValExprs;
3077  if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
3078  ValExprs))
3079  return nullptr;
3080 
3081  return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,
3082  OpenLoc, CloseLoc);
3083 }
3084 
3085 OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
3086  SourceLocation Loc = Tok.getLocation();
3087  ConsumeAnyToken();
3088 
3089  // Parse '('.
3090  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3091  if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))
3092  return nullptr;
3094  do {
3095  CXXScopeSpec SS;
3096  Token Replacement;
3097  ExprResult Allocator =
3098  getLangOpts().CPlusPlus
3099  ? ParseCXXIdExpression()
3100  : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
3101  Replacement);
3102  if (Allocator.isInvalid()) {
3103  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3104  StopBeforeMatch);
3105  break;
3106  }
3107  SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
3108  D.Allocator = Allocator.get();
3109  if (Tok.is(tok::l_paren)) {
3110  BalancedDelimiterTracker T(*this, tok::l_paren,
3111  tok::annot_pragma_openmp_end);
3112  T.consumeOpen();
3113  ExprResult AllocatorTraits =
3114  getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
3115  T.consumeClose();
3116  if (AllocatorTraits.isInvalid()) {
3117  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3118  StopBeforeMatch);
3119  break;
3120  }
3121  D.AllocatorTraits = AllocatorTraits.get();
3122  D.LParenLoc = T.getOpenLocation();
3123  D.RParenLoc = T.getCloseLocation();
3124  }
3125  if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
3126  Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;
3127  // Parse ','
3128  if (Tok.is(tok::comma))
3129  ConsumeAnyToken();
3130  } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));
3131  T.consumeClose();
3132  return Actions.OpenMP().ActOnOpenMPUsesAllocatorClause(
3133  Loc, T.getOpenLocation(), T.getCloseLocation(), Data);
3134 }
3135 
3136 /// Parsing of OpenMP clauses.
3137 ///
3138 /// clause:
3139 /// if-clause | final-clause | num_threads-clause | safelen-clause |
3140 /// default-clause | private-clause | firstprivate-clause | shared-clause
3141 /// | linear-clause | aligned-clause | collapse-clause | bind-clause |
3142 /// lastprivate-clause | reduction-clause | proc_bind-clause |
3143 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
3144 /// mergeable-clause | flush-clause | read-clause | write-clause |
3145 /// update-clause | capture-clause | seq_cst-clause | device-clause |
3146 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
3147 /// thread_limit-clause | priority-clause | grainsize-clause |
3148 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
3149 /// from-clause | is_device_ptr-clause | task_reduction-clause |
3150 /// in_reduction-clause | allocator-clause | allocate-clause |
3151 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
3152 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause |
3153 /// exclusive-clause | uses_allocators-clause | use_device_addr-clause |
3154 /// has_device_addr
3155 ///
3156 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
3157  OpenMPClauseKind CKind, bool FirstClause) {
3158  OMPClauseKind = CKind;
3159  OMPClause *Clause = nullptr;
3160  bool ErrorFound = false;
3161  bool WrongDirective = false;
3162  // Check if clause is allowed for the given directive.
3163  if (CKind != OMPC_unknown &&
3164  !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
3165  Diag(Tok, diag::err_omp_unexpected_clause)
3166  << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3167  ErrorFound = true;
3168  WrongDirective = true;
3169  }
3170 
3171  switch (CKind) {
3172  case OMPC_final:
3173  case OMPC_num_threads:
3174  case OMPC_safelen:
3175  case OMPC_simdlen:
3176  case OMPC_collapse:
3177  case OMPC_ordered:
3178  case OMPC_priority:
3179  case OMPC_grainsize:
3180  case OMPC_num_tasks:
3181  case OMPC_hint:
3182  case OMPC_allocator:
3183  case OMPC_depobj:
3184  case OMPC_detach:
3185  case OMPC_novariants:
3186  case OMPC_nocontext:
3187  case OMPC_filter:
3188  case OMPC_partial:
3189  case OMPC_align:
3190  case OMPC_message:
3191  case OMPC_ompx_dyn_cgroup_mem:
3192  // OpenMP [2.5, Restrictions]
3193  // At most one num_threads clause can appear on the directive.
3194  // OpenMP [2.8.1, simd construct, Restrictions]
3195  // Only one safelen clause can appear on a simd directive.
3196  // Only one simdlen clause can appear on a simd directive.
3197  // Only one collapse clause can appear on a simd directive.
3198  // OpenMP [2.11.1, task Construct, Restrictions]
3199  // At most one if clause can appear on the directive.
3200  // At most one final clause can appear on the directive.
3201  // OpenMP [teams Construct, Restrictions]
3202  // At most one num_teams clause can appear on the directive.
3203  // At most one thread_limit clause can appear on the directive.
3204  // OpenMP [2.9.1, task Construct, Restrictions]
3205  // At most one priority clause can appear on the directive.
3206  // OpenMP [2.9.2, taskloop Construct, Restrictions]
3207  // At most one grainsize clause can appear on the directive.
3208  // OpenMP [2.9.2, taskloop Construct, Restrictions]
3209  // At most one num_tasks clause can appear on the directive.
3210  // OpenMP [2.11.3, allocate Directive, Restrictions]
3211  // At most one allocator clause can appear on the directive.
3212  // OpenMP 5.0, 2.10.1 task Construct, Restrictions.
3213  // At most one detach clause can appear on the directive.
3214  // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
3215  // At most one novariants clause can appear on a dispatch directive.
3216  // At most one nocontext clause can appear on a dispatch directive.
3217  // OpenMP [5.1, error directive, Restrictions]
3218  // At most one message clause can appear on the directive
3219  if (!FirstClause) {
3220  Diag(Tok, diag::err_omp_more_one_clause)
3221  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3222  ErrorFound = true;
3223  }
3224 
3225  if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3226  PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
3227  Clause = ParseOpenMPClause(CKind, WrongDirective);
3228  else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
3229  Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3230  else
3231  Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3232  break;
3233  case OMPC_fail:
3234  case OMPC_default:
3235  case OMPC_proc_bind:
3236  case OMPC_atomic_default_mem_order:
3237  case OMPC_at:
3238  case OMPC_severity:
3239  case OMPC_bind:
3240  // OpenMP [2.14.3.1, Restrictions]
3241  // Only a single default clause may be specified on a parallel, task or
3242  // teams directive.
3243  // OpenMP [2.5, parallel Construct, Restrictions]
3244  // At most one proc_bind clause can appear on the directive.
3245  // OpenMP [5.0, Requires directive, Restrictions]
3246  // At most one atomic_default_mem_order clause can appear
3247  // on the directive
3248  // OpenMP [5.1, error directive, Restrictions]
3249  // At most one at clause can appear on the directive
3250  // At most one severity clause can appear on the directive
3251  // OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
3252  // At most one bind clause can appear on a loop directive.
3253  if (!FirstClause) {
3254  Diag(Tok, diag::err_omp_more_one_clause)
3255  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3256  ErrorFound = true;
3257  }
3258 
3259  Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3260  break;
3261  case OMPC_device:
3262  case OMPC_schedule:
3263  case OMPC_dist_schedule:
3264  case OMPC_defaultmap:
3265  case OMPC_order:
3266  // OpenMP [2.7.1, Restrictions, p. 3]
3267  // Only one schedule clause can appear on a loop directive.
3268  // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
3269  // At most one defaultmap clause can appear on the directive.
3270  // OpenMP 5.0 [2.12.5, target construct, Restrictions]
3271  // At most one device clause can appear on the directive.
3272  // OpenMP 5.1 [2.11.3, order clause, Restrictions]
3273  // At most one order clause may appear on a construct.
3274  if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3275  (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
3276  Diag(Tok, diag::err_omp_more_one_clause)
3277  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3278  ErrorFound = true;
3279  }
3280  [[fallthrough]];
3281  case OMPC_if:
3282  Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3283  break;
3284  case OMPC_holds:
3285  Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3286  break;
3287  case OMPC_nowait:
3288  case OMPC_untied:
3289  case OMPC_mergeable:
3290  case OMPC_read:
3291  case OMPC_write:
3292  case OMPC_capture:
3293  case OMPC_compare:
3294  case OMPC_seq_cst:
3295  case OMPC_acq_rel:
3296  case OMPC_acquire:
3297  case OMPC_release:
3298  case OMPC_relaxed:
3299  case OMPC_weak:
3300  case OMPC_threads:
3301  case OMPC_simd:
3302  case OMPC_nogroup:
3303  case OMPC_unified_address:
3304  case OMPC_unified_shared_memory:
3305  case OMPC_reverse_offload:
3306  case OMPC_dynamic_allocators:
3307  case OMPC_full:
3308  // OpenMP [2.7.1, Restrictions, p. 9]
3309  // Only one ordered clause can appear on a loop directive.
3310  // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
3311  // Only one nowait clause can appear on a for directive.
3312  // OpenMP [5.0, Requires directive, Restrictions]
3313  // Each of the requires clauses can appear at most once on the directive.
3314  if (!FirstClause) {
3315  Diag(Tok, diag::err_omp_more_one_clause)
3316  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3317  ErrorFound = true;
3318  }
3319 
3320  Clause = ParseOpenMPClause(CKind, WrongDirective);
3321  break;
3322  case OMPC_update:
3323  if (!FirstClause) {
3324  Diag(Tok, diag::err_omp_more_one_clause)
3325  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3326  ErrorFound = true;
3327  }
3328 
3329  Clause = (DKind == OMPD_depobj)
3330  ? ParseOpenMPSimpleClause(CKind, WrongDirective)
3331  : ParseOpenMPClause(CKind, WrongDirective);
3332  break;
3333  case OMPC_num_teams:
3334  case OMPC_thread_limit:
3335  if (!FirstClause) {
3336  Diag(Tok, diag::err_omp_more_one_clause)
3337  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3338  ErrorFound = true;
3339  }
3340  [[fallthrough]];
3341  case OMPC_private:
3342  case OMPC_firstprivate:
3343  case OMPC_lastprivate:
3344  case OMPC_shared:
3345  case OMPC_reduction:
3346  case OMPC_task_reduction:
3347  case OMPC_in_reduction:
3348  case OMPC_linear:
3349  case OMPC_aligned:
3350  case OMPC_copyin:
3351  case OMPC_copyprivate:
3352  case OMPC_flush:
3353  case OMPC_depend:
3354  case OMPC_map:
3355  case OMPC_to:
3356  case OMPC_from:
3357  case OMPC_use_device_ptr:
3358  case OMPC_use_device_addr:
3359  case OMPC_is_device_ptr:
3360  case OMPC_has_device_addr:
3361  case OMPC_allocate:
3362  case OMPC_nontemporal:
3363  case OMPC_inclusive:
3364  case OMPC_exclusive:
3365  case OMPC_affinity:
3366  case OMPC_doacross:
3367  case OMPC_enter:
3368  if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
3369  CKind == OMPC_depend)
3370  Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3371  Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3372  break;
3373  case OMPC_sizes:
3374  if (!FirstClause) {
3375  Diag(Tok, diag::err_omp_more_one_clause)
3376  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3377  ErrorFound = true;
3378  }
3379 
3380  Clause = ParseOpenMPSizesClause();
3381  break;
3382  case OMPC_uses_allocators:
3383  Clause = ParseOpenMPUsesAllocatorClause(DKind);
3384  break;
3385  case OMPC_destroy:
3386  if (DKind != OMPD_interop) {
3387  if (!FirstClause) {
3388  Diag(Tok, diag::err_omp_more_one_clause)
3389  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3390  ErrorFound = true;
3391  }
3392  Clause = ParseOpenMPClause(CKind, WrongDirective);
3393  break;
3394  }
3395  [[fallthrough]];
3396  case OMPC_init:
3397  case OMPC_use:
3398  Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3399  break;
3400  case OMPC_device_type:
3401  case OMPC_unknown:
3402  skipUntilPragmaOpenMPEnd(DKind);
3403  break;
3404  case OMPC_threadprivate:
3405  case OMPC_uniform:
3406  case OMPC_match:
3407  if (!WrongDirective)
3408  Diag(Tok, diag::err_omp_unexpected_clause)
3409  << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3410  SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
3411  break;
3412  case OMPC_absent:
3413  case OMPC_contains: {
3414  SourceLocation Loc = ConsumeToken();
3415  SourceLocation LLoc = Tok.getLocation();
3416  SourceLocation RLoc;
3418  BalancedDelimiterTracker T(*this, tok::l_paren);
3419  T.consumeOpen();
3420  do {
3421  OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
3422  if (DK == OMPD_unknown) {
3423  skipUntilPragmaOpenMPEnd(OMPD_assume);
3424  Diag(Tok, diag::err_omp_unexpected_clause)
3425  << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3426  break;
3427  }
3428  if (isOpenMPExecutableDirective(DK)) {
3429  DKVec.push_back(DK);
3430  ConsumeToken();
3431  } else {
3432  Diag(Tok, diag::err_omp_unexpected_clause)
3433  << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3434  }
3435  } while (TryConsumeToken(tok::comma));
3436  RLoc = Tok.getLocation();
3437  T.consumeClose();
3438  Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
3439  CKind, DKVec, Loc, LLoc, RLoc);
3440  break;
3441  }
3442  case OMPC_no_openmp:
3443  case OMPC_no_openmp_routines:
3444  case OMPC_no_parallelism: {
3445  if (!FirstClause) {
3446  Diag(Tok, diag::err_omp_more_one_clause)
3447  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3448  ErrorFound = true;
3449  }
3450  SourceLocation Loc = ConsumeToken();
3451  Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
3452  CKind, Loc, Tok.getLocation());
3453  break;
3454  }
3455  case OMPC_ompx_attribute:
3456  Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3457  break;
3458  case OMPC_ompx_bare:
3459  if (WrongDirective)
3460  Diag(Tok, diag::note_ompx_bare_clause)
3461  << getOpenMPClauseName(CKind) << "target teams";
3462  if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
3463  Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3464  << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3465  ErrorFound = true;
3466  }
3467  Clause = ParseOpenMPClause(CKind, WrongDirective);
3468  break;
3469  default:
3470  break;
3471  }
3472  return ErrorFound ? nullptr : Clause;
3473 }
3474 
3475 /// Parses simple expression in parens for single-expression clauses of OpenMP
3476 /// constructs.
3477 /// \param RLoc Returned location of right paren.
3479  SourceLocation &RLoc,
3480  bool IsAddressOfOperand) {
3481  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3482  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3483  return ExprError();
3484 
3485  SourceLocation ELoc = Tok.getLocation();
3486  ExprResult LHS(
3487  ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast));
3488  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3489  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
3490 
3491  // Parse ')'.
3492  RLoc = Tok.getLocation();
3493  if (!T.consumeClose())
3494  RLoc = T.getCloseLocation();
3495 
3496  return Val;
3497 }
3498 
3499 /// Parsing of OpenMP clauses with single expressions like 'final',
3500 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
3501 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or
3502 /// 'detach'.
3503 ///
3504 /// final-clause:
3505 /// 'final' '(' expression ')'
3506 ///
3507 /// num_threads-clause:
3508 /// 'num_threads' '(' expression ')'
3509 ///
3510 /// safelen-clause:
3511 /// 'safelen' '(' expression ')'
3512 ///
3513 /// simdlen-clause:
3514 /// 'simdlen' '(' expression ')'
3515 ///
3516 /// collapse-clause:
3517 /// 'collapse' '(' expression ')'
3518 ///
3519 /// priority-clause:
3520 /// 'priority' '(' expression ')'
3521 ///
3522 /// grainsize-clause:
3523 /// 'grainsize' '(' expression ')'
3524 ///
3525 /// num_tasks-clause:
3526 /// 'num_tasks' '(' expression ')'
3527 ///
3528 /// hint-clause:
3529 /// 'hint' '(' expression ')'
3530 ///
3531 /// allocator-clause:
3532 /// 'allocator' '(' expression ')'
3533 ///
3534 /// detach-clause:
3535 /// 'detach' '(' event-handler-expression ')'
3536 ///
3537 /// align-clause
3538 /// 'align' '(' positive-integer-constant ')'
3539 ///
3540 /// holds-clause
3541 /// 'holds' '(' expression ')'
3542 ///
3543 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
3544  bool ParseOnly) {
3545  SourceLocation Loc = ConsumeToken();
3546  SourceLocation LLoc = Tok.getLocation();
3547  SourceLocation RLoc;
3548 
3549  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
3550 
3551  if (Val.isInvalid())
3552  return nullptr;
3553 
3554  if (ParseOnly)
3555  return nullptr;
3556  return Actions.OpenMP().ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc,
3557  LLoc, RLoc);
3558 }
3559 
3560 /// Parse indirect clause for '#pragma omp declare target' directive.
3561 /// 'indirect' '[' '(' invoked-by-fptr ')' ']'
3562 /// where invoked-by-fptr is a constant boolean expression that evaluates to
3563 /// true or false at compile time.
3564 bool Parser::ParseOpenMPIndirectClause(
3565  SemaOpenMP::DeclareTargetContextInfo &DTCI, bool ParseOnly) {
3566  SourceLocation Loc = ConsumeToken();
3567  SourceLocation RLoc;
3568 
3569  if (Tok.isNot(tok::l_paren)) {
3570  if (ParseOnly)
3571  return false;
3572  DTCI.Indirect = nullptr;
3573  return true;
3574  }
3575 
3576  ExprResult Val =
3577  ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc);
3578  if (Val.isInvalid())
3579  return false;
3580 
3581  if (ParseOnly)
3582  return false;
3583 
3584  if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() &&
3585  !Val.get()->isInstantiationDependent() &&
3587  ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());
3588  if (Ret.isInvalid())
3589  return false;
3590  llvm::APSInt Result;
3591  Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,
3592  Sema::AllowFold);
3593  if (Ret.isInvalid())
3594  return false;
3595  DTCI.Indirect = Val.get();
3596  return true;
3597  }
3598  return false;
3599 }
3600 
3601 /// Parses a comma-separated list of interop-types and a prefer_type list.
3602 ///
3603 bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
3605  const Token &Tok = getCurToken();
3606  bool HasError = false;
3607  bool IsTarget = false;
3608  bool IsTargetSync = false;
3609 
3610  while (Tok.is(tok::identifier)) {
3611  // Currently prefer_type is only allowed with 'init' and it must be first.
3612  bool PreferTypeAllowed = Kind == OMPC_init &&
3613  InteropInfo.PreferTypes.empty() && !IsTarget &&
3614  !IsTargetSync;
3615  if (Tok.getIdentifierInfo()->isStr("target")) {
3616  // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3617  // Each interop-type may be specified on an action-clause at most
3618  // once.
3619  if (IsTarget)
3620  Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
3621  IsTarget = true;
3622  ConsumeToken();
3623  } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
3624  if (IsTargetSync)
3625  Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
3626  IsTargetSync = true;
3627  ConsumeToken();
3628  } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
3629  PreferTypeAllowed) {
3630  ConsumeToken();
3631  BalancedDelimiterTracker PT(*this, tok::l_paren,
3632  tok::annot_pragma_openmp_end);
3633  if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
3634  HasError = true;
3635 
3636  while (Tok.isNot(tok::r_paren)) {
3637  SourceLocation Loc = Tok.getLocation();
3638  ExprResult LHS = ParseCastExpression(AnyCastExpr);
3639  ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
3640  ParseRHSOfBinaryExpression(LHS, prec::Conditional));
3641  PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
3642  /*DiscardedValue=*/false);
3643  if (PTExpr.isUsable()) {
3644  InteropInfo.PreferTypes.push_back(PTExpr.get());
3645  } else {
3646  HasError = true;
3647  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3648  StopBeforeMatch);
3649  }
3650 
3651  if (Tok.is(tok::comma))
3652  ConsumeToken();
3653  }
3654  PT.consumeClose();
3655  } else {
3656  HasError = true;
3657  Diag(Tok, diag::err_omp_expected_interop_type);
3658  ConsumeToken();
3659  }
3660  if (!Tok.is(tok::comma))
3661  break;
3662  ConsumeToken();
3663  }
3664 
3665  if (!HasError && !IsTarget && !IsTargetSync) {
3666  Diag(Tok, diag::err_omp_expected_interop_type);
3667  HasError = true;
3668  }
3669 
3670  if (Kind == OMPC_init) {
3671  if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
3672  Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
3673  if (Tok.is(tok::colon))
3674  ConsumeToken();
3675  }
3676 
3677  // As of OpenMP 5.1,there are two interop-types, "target" and
3678  // "targetsync". Either or both are allowed for a single interop.
3679  InteropInfo.IsTarget = IsTarget;
3680  InteropInfo.IsTargetSync = IsTargetSync;
3681 
3682  return HasError;
3683 }
3684 
3685 /// Parsing of OpenMP clauses that use an interop-var.
3686 ///
3687 /// init-clause:
3688 /// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var)
3689 ///
3690 /// destroy-clause:
3691 /// destroy(interop-var)
3692 ///
3693 /// use-clause:
3694 /// use(interop-var)
3695 ///
3696 /// interop-modifier:
3697 /// prefer_type(preference-list)
3698 ///
3699 /// preference-list:
3700 /// foreign-runtime-id [, foreign-runtime-id]...
3701 ///
3702 /// foreign-runtime-id:
3703 /// <string-literal> | <constant-integral-expression>
3704 ///
3705 /// interop-type:
3706 /// target | targetsync
3707 ///
3708 OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
3709  bool ParseOnly) {
3710  SourceLocation Loc = ConsumeToken();
3711  // Parse '('.
3712  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3713  if (T.expectAndConsume(diag::err_expected_lparen_after,
3714  getOpenMPClauseName(Kind).data()))
3715  return nullptr;
3716 
3717  bool InteropError = false;
3718  OMPInteropInfo InteropInfo;
3719  if (Kind == OMPC_init)
3720  InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3721 
3722  // Parse the variable.
3723  SourceLocation VarLoc = Tok.getLocation();
3724  ExprResult InteropVarExpr =
3725  Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
3726  if (!InteropVarExpr.isUsable()) {
3727  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3728  StopBeforeMatch);
3729  }
3730 
3731  // Parse ')'.
3732  SourceLocation RLoc = Tok.getLocation();
3733  if (!T.consumeClose())
3734  RLoc = T.getCloseLocation();
3735 
3736  if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
3737  return nullptr;
3738 
3739  if (Kind == OMPC_init)
3740  return Actions.OpenMP().ActOnOpenMPInitClause(
3741  InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,
3742  RLoc);
3743  if (Kind == OMPC_use)
3744  return Actions.OpenMP().ActOnOpenMPUseClause(
3745  InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3746 
3747  if (Kind == OMPC_destroy)
3748  return Actions.OpenMP().ActOnOpenMPDestroyClause(
3749  InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);
3750 
3751  llvm_unreachable("Unexpected interop variable clause.");
3752 }
3753 
3754 OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {
3755  SourceLocation Loc = ConsumeToken();
3756  // Parse '('.
3757  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3758  if (T.expectAndConsume(diag::err_expected_lparen_after,
3759  getOpenMPClauseName(OMPC_ompx_attribute).data()))
3760  return nullptr;
3761 
3762  ParsedAttributes ParsedAttrs(AttrFactory);
3763  ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
3764 
3765  // Parse ')'.
3766  if (T.consumeClose())
3767  return nullptr;
3768 
3769  if (ParseOnly)
3770  return nullptr;
3771 
3772  SmallVector<Attr *> Attrs;
3773  for (const ParsedAttr &PA : ParsedAttrs) {
3774  switch (PA.getKind()) {
3775  case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
3776  if (!PA.checkExactlyNumArgs(Actions, 2))
3777  continue;
3778  if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(
3779  PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
3780  Attrs.push_back(A);
3781  continue;
3782  case ParsedAttr::AT_AMDGPUWavesPerEU:
3783  if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3784  !PA.checkAtMostNumArgs(Actions, 2))
3785  continue;
3786  if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(
3787  PA, PA.getArgAsExpr(0),
3788  PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))
3789  Attrs.push_back(A);
3790  continue;
3791  case ParsedAttr::AT_CUDALaunchBounds:
3792  if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3793  !PA.checkAtMostNumArgs(Actions, 2))
3794  continue;
3795  if (auto *A = Actions.CreateLaunchBoundsAttr(
3796  PA, PA.getArgAsExpr(0),
3797  PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,
3798  PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))
3799  Attrs.push_back(A);
3800  continue;
3801  default:
3802  Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3803  continue;
3804  };
3805  }
3806 
3807  return Actions.OpenMP().ActOnOpenMPXAttributeClause(
3808  Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());
3809 }
3810 
3811 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
3812 ///
3813 /// default-clause:
3814 /// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')'
3815 ///
3816 /// proc_bind-clause:
3817 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')'
3818 ///
3819 /// bind-clause:
3820 /// 'bind' '(' 'teams' | 'parallel' | 'thread' ')'
3821 ///
3822 /// update-clause:
3823 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' |
3824 /// 'inoutset' ')'
3825 ///
3826 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
3827  bool ParseOnly) {
3828  std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
3829  if (!Val || ParseOnly)
3830  return nullptr;
3831  if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3832  (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
3833  static_cast<DefaultKind>(Val->Type) ==
3834  OMP_DEFAULT_firstprivate)) {
3835  Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3836  << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
3837  OMP_DEFAULT_private
3838  ? OMPC_private
3839  : OMPC_firstprivate)
3840  << getOpenMPClauseName(OMPC_default) << "5.1";
3841  return nullptr;
3842  }
3843  return Actions.OpenMP().ActOnOpenMPSimpleClause(
3844  Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
3845 }
3846 
3847 /// Parsing of OpenMP clauses like 'ordered'.
3848 ///
3849 /// ordered-clause:
3850 /// 'ordered'
3851 ///
3852 /// nowait-clause:
3853 /// 'nowait'
3854 ///
3855 /// untied-clause:
3856 /// 'untied'
3857 ///
3858 /// mergeable-clause:
3859 /// 'mergeable'
3860 ///
3861 /// read-clause:
3862 /// 'read'
3863 ///
3864 /// threads-clause:
3865 /// 'threads'
3866 ///
3867 /// simd-clause:
3868 /// 'simd'
3869 ///
3870 /// nogroup-clause:
3871 /// 'nogroup'
3872 ///
3873 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
3874  SourceLocation Loc = Tok.getLocation();
3875  ConsumeAnyToken();
3876 
3877  if (ParseOnly)
3878  return nullptr;
3879  return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
3880 }
3881 
3882 /// Parsing of OpenMP clauses with single expressions and some additional
3883 /// argument like 'schedule' or 'dist_schedule'.
3884 ///
3885 /// schedule-clause:
3886 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
3887 /// ')'
3888 ///
3889 /// if-clause:
3890 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
3891 ///
3892 /// defaultmap:
3893 /// 'defaultmap' '(' modifier [ ':' kind ] ')'
3894 ///
3895 /// device-clause:
3896 /// 'device' '(' [ device-modifier ':' ] expression ')'
3897 ///
3898 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
3900  bool ParseOnly) {
3901  SourceLocation Loc = ConsumeToken();
3902  SourceLocation DelimLoc;
3903  // Parse '('.
3904  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
3905  if (T.expectAndConsume(diag::err_expected_lparen_after,
3906  getOpenMPClauseName(Kind).data()))
3907  return nullptr;
3908 
3909  ExprResult Val;
3912  if (Kind == OMPC_schedule) {
3913  enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3914  Arg.resize(NumberOfElements);
3915  KLoc.resize(NumberOfElements);
3916  Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
3917  Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
3918  Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
3919  unsigned KindModifier = getOpenMPSimpleClauseType(
3920  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3921  if (KindModifier > OMPC_SCHEDULE_unknown) {
3922  // Parse 'modifier'
3923  Arg[Modifier1] = KindModifier;
3924  KLoc[Modifier1] = Tok.getLocation();
3925  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3926  Tok.isNot(tok::annot_pragma_openmp_end))
3927  ConsumeAnyToken();
3928  if (Tok.is(tok::comma)) {
3929  // Parse ',' 'modifier'
3930  ConsumeAnyToken();
3931  KindModifier = getOpenMPSimpleClauseType(
3932  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3933  Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
3934  ? KindModifier
3936  KLoc[Modifier2] = Tok.getLocation();
3937  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3938  Tok.isNot(tok::annot_pragma_openmp_end))
3939  ConsumeAnyToken();
3940  }
3941  // Parse ':'
3942  if (Tok.is(tok::colon))
3943  ConsumeAnyToken();
3944  else
3945  Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
3946  KindModifier = getOpenMPSimpleClauseType(
3947  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3948  }
3949  Arg[ScheduleKind] = KindModifier;
3950  KLoc[ScheduleKind] = Tok.getLocation();
3951  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3952  Tok.isNot(tok::annot_pragma_openmp_end))
3953  ConsumeAnyToken();
3954  if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3955  Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3956  Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3957  Tok.is(tok::comma))
3958  DelimLoc = ConsumeAnyToken();
3959  } else if (Kind == OMPC_dist_schedule) {
3960  Arg.push_back(getOpenMPSimpleClauseType(
3961  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3962  KLoc.push_back(Tok.getLocation());
3963  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3964  Tok.isNot(tok::annot_pragma_openmp_end))
3965  ConsumeAnyToken();
3966  if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
3967  DelimLoc = ConsumeAnyToken();
3968  } else if (Kind == OMPC_defaultmap) {
3969  // Get a defaultmap modifier
3970  unsigned Modifier = getOpenMPSimpleClauseType(
3971  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
3972 
3973  // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
3974  // pointer
3975  if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
3977  Arg.push_back(Modifier);
3978  KLoc.push_back(Tok.getLocation());
3979  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3980  Tok.isNot(tok::annot_pragma_openmp_end))
3981  ConsumeAnyToken();
3982  // Parse ':'
3983  if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {
3984  if (Tok.is(tok::colon))
3985  ConsumeAnyToken();
3986  else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
3987  Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
3988  // Get a defaultmap kind
3989  Arg.push_back(getOpenMPSimpleClauseType(
3990  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
3991  KLoc.push_back(Tok.getLocation());
3992  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
3993  Tok.isNot(tok::annot_pragma_openmp_end))
3994  ConsumeAnyToken();
3995  } else {
3996  Arg.push_back(OMPC_DEFAULTMAP_unknown);
3997  KLoc.push_back(SourceLocation());
3998  }
3999  } else if (Kind == OMPC_order) {
4000  enum { Modifier, OrderKind, NumberOfElements };
4001  Arg.resize(NumberOfElements);
4002  KLoc.resize(NumberOfElements);
4003  Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
4004  Arg[OrderKind] = OMPC_ORDER_unknown;
4005  unsigned KindModifier = getOpenMPSimpleClauseType(
4006  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4007  if (KindModifier > OMPC_ORDER_unknown) {
4008  // Parse 'modifier'
4009  Arg[Modifier] = KindModifier;
4010  KLoc[Modifier] = Tok.getLocation();
4011  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4012  Tok.isNot(tok::annot_pragma_openmp_end))
4013  ConsumeAnyToken();
4014  // Parse ':'
4015  if (Tok.is(tok::colon))
4016  ConsumeAnyToken();
4017  else
4018  Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
4019  KindModifier = getOpenMPSimpleClauseType(
4020  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
4021  }
4022  Arg[OrderKind] = KindModifier;
4023  KLoc[OrderKind] = Tok.getLocation();
4024  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
4025  Tok.isNot(tok::annot_pragma_openmp_end))
4026  ConsumeAnyToken();
4027  } else if (Kind == OMPC_device) {
4028  // Only target executable directives support extended device construct.
4029  if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
4030  NextToken().is(tok::colon)) {
4031  // Parse optional <device modifier> ':'
4032  Arg.push_back(getOpenMPSimpleClauseType(
4033  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));
4034  KLoc.push_back(Tok.getLocation());
4035  ConsumeAnyToken();
4036  // Parse ':'
4037  ConsumeAnyToken();
4038  } else {
4039  Arg.push_back(OMPC_DEVICE_unknown);
4040  KLoc.emplace_back();
4041  }
4042  } else if (Kind == OMPC_grainsize) {
4043  // Parse optional <grainsize modifier> ':'
4046  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4047  getLangOpts()));
4048  if (getLangOpts().OpenMP >= 51) {
4049  if (NextToken().is(tok::colon)) {
4050  Arg.push_back(Modifier);
4051  KLoc.push_back(Tok.getLocation());
4052  // Parse modifier
4053  ConsumeAnyToken();
4054  // Parse ':'
4055  ConsumeAnyToken();
4056  } else {
4057  if (Modifier == OMPC_GRAINSIZE_strict) {
4058  Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4059  // Parse modifier
4060  ConsumeAnyToken();
4061  }
4062  Arg.push_back(OMPC_GRAINSIZE_unknown);
4063  KLoc.emplace_back();
4064  }
4065  } else {
4066  Arg.push_back(OMPC_GRAINSIZE_unknown);
4067  KLoc.emplace_back();
4068  }
4069  } else if (Kind == OMPC_num_tasks) {
4070  // Parse optional <num_tasks modifier> ':'
4071  OpenMPNumTasksClauseModifier Modifier =
4073  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4074  getLangOpts()));
4075  if (getLangOpts().OpenMP >= 51) {
4076  if (NextToken().is(tok::colon)) {
4077  Arg.push_back(Modifier);
4078  KLoc.push_back(Tok.getLocation());
4079  // Parse modifier
4080  ConsumeAnyToken();
4081  // Parse ':'
4082  ConsumeAnyToken();
4083  } else {
4084  if (Modifier == OMPC_NUMTASKS_strict) {
4085  Diag(Tok, diag::err_modifier_expected_colon) << "strict";
4086  // Parse modifier
4087  ConsumeAnyToken();
4088  }
4089  Arg.push_back(OMPC_NUMTASKS_unknown);
4090  KLoc.emplace_back();
4091  }
4092  } else {
4093  Arg.push_back(OMPC_NUMTASKS_unknown);
4094  KLoc.emplace_back();
4095  }
4096  } else {
4097  assert(Kind == OMPC_if);
4098  KLoc.push_back(Tok.getLocation());
4099  TentativeParsingAction TPA(*this);
4100  auto DK = parseOpenMPDirectiveKind(*this);
4101  Arg.push_back(DK);
4102  if (DK != OMPD_unknown) {
4103  ConsumeToken();
4104  if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
4105  TPA.Commit();
4106  DelimLoc = ConsumeToken();
4107  } else {
4108  TPA.Revert();
4109  Arg.back() = unsigned(OMPD_unknown);
4110  }
4111  } else {
4112  TPA.Revert();
4113  }
4114  }
4115 
4116  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
4117  (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
4118  Kind == OMPC_if || Kind == OMPC_device ||
4119  Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
4120  if (NeedAnExpression) {
4121  SourceLocation ELoc = Tok.getLocation();
4122  ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
4123  Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
4124  Val =
4125  Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
4126  }
4127 
4128  // Parse ')'.
4129  SourceLocation RLoc = Tok.getLocation();
4130  if (!T.consumeClose())
4131  RLoc = T.getCloseLocation();
4132 
4133  if (NeedAnExpression && Val.isInvalid())
4134  return nullptr;
4135 
4136  if (ParseOnly)
4137  return nullptr;
4138  return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(
4139  Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4140 }
4141 
4142 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
4143  UnqualifiedId &ReductionId) {
4144  if (ReductionIdScopeSpec.isEmpty()) {
4145  auto OOK = OO_None;
4146  switch (P.getCurToken().getKind()) {
4147  case tok::plus:
4148  OOK = OO_Plus;
4149  break;
4150  case tok::minus:
4151  OOK = OO_Minus;
4152  break;
4153  case tok::star:
4154  OOK = OO_Star;
4155  break;
4156  case tok::amp:
4157  OOK = OO_Amp;
4158  break;
4159  case tok::pipe:
4160  OOK = OO_Pipe;
4161  break;
4162  case tok::caret:
4163  OOK = OO_Caret;
4164  break;
4165  case tok::ampamp:
4166  OOK = OO_AmpAmp;
4167  break;
4168  case tok::pipepipe:
4169  OOK = OO_PipePipe;
4170  break;
4171  default:
4172  break;
4173  }
4174  if (OOK != OO_None) {
4175  SourceLocation OpLoc = P.ConsumeToken();
4176  SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
4177  ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
4178  return false;
4179  }
4180  }
4181  return P.ParseUnqualifiedId(
4182  ReductionIdScopeSpec, /*ObjectType=*/nullptr,
4183  /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
4184  /*AllowDestructorName*/ false,
4185  /*AllowConstructorName*/ false,
4186  /*AllowDeductionGuide*/ false, nullptr, ReductionId);
4187 }
4188 
4189 /// Checks if the token is a valid map-type-modifier.
4190 /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses.
4192  Token Tok = P.getCurToken();
4193  if (!Tok.is(tok::identifier))
4195 
4196  Preprocessor &PP = P.getPreprocessor();
4199  OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
4200  return TypeModifier;
4201 }
4202 
4203 /// Parse the mapper modifier in map, to, and from clauses.
4205  // Parse '('.
4206  BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
4207  if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
4208  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4209  StopBeforeMatch);
4210  return true;
4211  }
4212  // Parse mapper-identifier
4213  if (getLangOpts().CPlusPlus)
4214  ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4215  /*ObjectType=*/nullptr,
4216  /*ObjectHasErrors=*/false,
4217  /*EnteringContext=*/false);
4218  if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
4219  Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
4220  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4221  StopBeforeMatch);
4222  return true;
4223  }
4224  auto &DeclNames = Actions.getASTContext().DeclarationNames;
4225  Data.ReductionOrMapperId = DeclarationNameInfo(
4226  DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
4227  ConsumeToken();
4228  // Parse ')'.
4229  return T.consumeClose();
4230 }
4231 
4233 
4234 /// Parse map-type-modifiers in map clause.
4235 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] [map-type] : ] list)
4236 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) |
4237 /// present
4238 /// where, map-type ::= alloc | delete | from | release | to | tofrom
4240  bool HasMapType = false;
4241  SourceLocation PreMapLoc = Tok.getLocation();
4242  StringRef PreMapName = "";
4243  while (getCurToken().isNot(tok::colon)) {
4245  OpenMPMapClauseKind MapKind = isMapType(*this);
4246  if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4247  TypeModifier == OMPC_MAP_MODIFIER_close ||
4248  TypeModifier == OMPC_MAP_MODIFIER_present ||
4249  TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4250  Data.MapTypeModifiers.push_back(TypeModifier);
4251  Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4252  if (PP.LookAhead(0).isNot(tok::comma) &&
4253  PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)
4254  Diag(Tok.getLocation(), diag::err_omp_missing_comma)
4255  << "map type modifier";
4256  ConsumeToken();
4257  } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4258  Data.MapTypeModifiers.push_back(TypeModifier);
4259  Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4260  ConsumeToken();
4261  if (parseMapperModifier(Data))
4262  return true;
4263  if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&
4264  getLangOpts().OpenMP >= 52)
4265  Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4266  << "map type modifier";
4267 
4268  } else if (getLangOpts().OpenMP >= 60 && MapKind != OMPC_MAP_unknown) {
4269  if (!HasMapType) {
4270  HasMapType = true;
4271  Data.ExtraModifier = MapKind;
4272  MapKind = OMPC_MAP_unknown;
4273  PreMapLoc = Tok.getLocation();
4274  PreMapName = Tok.getIdentifierInfo()->getName();
4275  } else {
4276  Diag(Tok, diag::err_omp_more_one_map_type);
4277  Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4278  << PreMapName;
4279  }
4280  ConsumeToken();
4281  } else {
4282  // For the case of unknown map-type-modifier or a map-type.
4283  // Map-type is followed by a colon; the function returns when it
4284  // encounters a token followed by a colon.
4285  if (Tok.is(tok::comma)) {
4286  Diag(Tok, diag::err_omp_map_type_modifier_missing);
4287  ConsumeToken();
4288  continue;
4289  }
4290  // Potential map-type token as it is followed by a colon.
4291  if (PP.LookAhead(0).is(tok::colon)) {
4292  if (getLangOpts().OpenMP >= 60) {
4293  break;
4294  } else {
4295  return false;
4296  }
4297  }
4298 
4299  Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4300  << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
4301  : 0)
4302  << getLangOpts().OpenMPExtensions;
4303  ConsumeToken();
4304  }
4305  if (getCurToken().is(tok::comma))
4306  ConsumeToken();
4307  }
4308  if (getLangOpts().OpenMP >= 60 && !HasMapType) {
4309  if (!Tok.is(tok::colon)) {
4310  Diag(Tok, diag::err_omp_unknown_map_type);
4311  ConsumeToken();
4312  } else {
4313  Data.ExtraModifier = OMPC_MAP_unknown;
4314  }
4315  }
4316  return false;
4317 }
4318 
4319 /// Checks if the token is a valid map-type.
4320 /// If it is not MapType kind, OMPC_MAP_unknown is returned.
4322  Token Tok = P.getCurToken();
4323  // The map-type token can be either an identifier or the C++ delete keyword.
4324  if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
4325  return OMPC_MAP_unknown;
4326  Preprocessor &PP = P.getPreprocessor();
4327  unsigned MapType =
4328  getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok), P.getLangOpts());
4329  if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4330  MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4331  MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4332  return static_cast<OpenMPMapClauseKind>(MapType);
4333  return OMPC_MAP_unknown;
4334 }
4335 
4336 /// Parse map-type in map clause.
4337 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
4338 /// where, map-type ::= to | from | tofrom | alloc | release | delete
4340  Token Tok = P.getCurToken();
4341  if (Tok.is(tok::colon)) {
4342  P.Diag(Tok, diag::err_omp_map_type_missing);
4343  return;
4344  }
4345  Data.ExtraModifier = isMapType(P);
4346  if (Data.ExtraModifier == OMPC_MAP_unknown)
4347  P.Diag(Tok, diag::err_omp_unknown_map_type);
4348  P.ConsumeToken();
4349 }
4350 
4351 /// Parses simple expression in parens for single-expression clauses of OpenMP
4352 /// constructs.
4353 ExprResult Parser::ParseOpenMPIteratorsExpr() {
4354  assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
4355  "Expected 'iterator' token.");
4356  SourceLocation IteratorKwLoc = ConsumeToken();
4357 
4358  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4359  if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
4360  return ExprError();
4361 
4362  SourceLocation LLoc = T.getOpenLocation();
4364  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
4365  // Check if the type parsing is required.
4366  ParsedType IteratorType;
4367  if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
4368  // identifier '=' is not found - parse type.
4369  TypeResult TR = ParseTypeName();
4370  if (TR.isInvalid()) {
4371  T.skipToEnd();
4372  return ExprError();
4373  }
4374  IteratorType = TR.get();
4375  }
4376 
4377  // Parse identifier.
4378  IdentifierInfo *II = nullptr;
4379  SourceLocation IdLoc;
4380  if (Tok.is(tok::identifier)) {
4381  II = Tok.getIdentifierInfo();
4382  IdLoc = ConsumeToken();
4383  } else {
4384  Diag(Tok, diag::err_expected_unqualified_id) << 0;
4385  }
4386 
4387  // Parse '='.
4388  SourceLocation AssignLoc;
4389  if (Tok.is(tok::equal))
4390  AssignLoc = ConsumeToken();
4391  else
4392  Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4393 
4394  // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
4395  ColonProtectionRAIIObject ColonRAII(*this);
4396  // Parse <begin>
4397  SourceLocation Loc = Tok.getLocation();
4398  ExprResult LHS = ParseCastExpression(AnyCastExpr);
4400  ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4401  Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
4402  /*DiscardedValue=*/false);
4403  // Parse ':'.
4404  SourceLocation ColonLoc;
4405  if (Tok.is(tok::colon))
4406  ColonLoc = ConsumeToken();
4407 
4408  // Parse <end>
4409  Loc = Tok.getLocation();
4410  LHS = ParseCastExpression(AnyCastExpr);
4412  ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4413  End = Actions.ActOnFinishFullExpr(End.get(), Loc,
4414  /*DiscardedValue=*/false);
4415 
4416  SourceLocation SecColonLoc;
4417  ExprResult Step;
4418  // Parse optional step.
4419  if (Tok.is(tok::colon)) {
4420  // Parse ':'
4421  SecColonLoc = ConsumeToken();
4422  // Parse <step>
4423  Loc = Tok.getLocation();
4424  LHS = ParseCastExpression(AnyCastExpr);
4425  Step = Actions.CorrectDelayedTyposInExpr(
4426  ParseRHSOfBinaryExpression(LHS, prec::Conditional));
4427  Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
4428  /*DiscardedValue=*/false);
4429  }
4430 
4431  // Parse ',' or ')'
4432  if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
4433  Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4434  if (Tok.is(tok::comma))
4435  ConsumeToken();
4436 
4437  SemaOpenMP::OMPIteratorData &D = Data.emplace_back();
4438  D.DeclIdent = II;
4439  D.DeclIdentLoc = IdLoc;
4440  D.Type = IteratorType;
4441  D.AssignLoc = AssignLoc;
4442  D.ColonLoc = ColonLoc;
4443  D.SecColonLoc = SecColonLoc;
4444  D.Range.Begin = Begin.get();
4445  D.Range.End = End.get();
4446  D.Range.Step = Step.get();
4447  }
4448 
4449  // Parse ')'.
4450  SourceLocation RLoc = Tok.getLocation();
4451  if (!T.consumeClose())
4452  RLoc = T.getCloseLocation();
4453 
4454  return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,
4455  LLoc, RLoc, Data);
4456 }
4457 
4460  const LangOptions &LangOpts) {
4461  // Currently the only reserved locator is 'omp_all_memory' which is only
4462  // allowed on a depend clause.
4463  if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4464  return false;
4465 
4466  if (Tok.is(tok::identifier) &&
4467  Tok.getIdentifierInfo()->isStr("omp_all_memory")) {
4468 
4469  if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4470  Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4471  Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4472  else if (Data.ExtraModifier != OMPC_DEPEND_out &&
4473  Data.ExtraModifier != OMPC_DEPEND_inout)
4474  Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4475  else
4476  Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out
4477  ? OMPC_DEPEND_outallmemory
4478  : OMPC_DEPEND_inoutallmemory;
4479  ConsumeToken();
4480  return true;
4481  }
4482  return false;
4483 }
4484 
4485 /// Parse step size expression. Returns true if parsing is successfull,
4486 /// otherwise returns false.
4488  OpenMPClauseKind CKind, SourceLocation ELoc) {
4489  ExprResult Tail = P.ParseAssignmentExpression();
4490  Sema &Actions = P.getActions();
4491  Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4492  /*DiscardedValue*/ false);
4493  if (Tail.isUsable()) {
4494  Data.DepModOrTailExpr = Tail.get();
4495  Token CurTok = P.getCurToken();
4496  if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {
4497  P.Diag(CurTok, diag::err_expected_punc) << "step expression";
4498  }
4499  return true;
4500  }
4501  return false;
4502 }
4503 
4504 /// Parses clauses with list.
4509  UnqualifiedId UnqualifiedReductionId;
4510  bool InvalidReductionId = false;
4511  bool IsInvalidMapperModifier = false;
4512 
4513  // Parse '('.
4514  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
4515  if (T.expectAndConsume(diag::err_expected_lparen_after,
4516  getOpenMPClauseName(Kind).data()))
4517  return true;
4518 
4519  bool HasIterator = false;
4520  bool InvalidIterator = false;
4521  bool NeedRParenForLinear = false;
4522  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
4523  tok::annot_pragma_openmp_end);
4524  // Handle reduction-identifier for reduction clause.
4525  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4526  Kind == OMPC_in_reduction) {
4527  Data.ExtraModifier = OMPC_REDUCTION_unknown;
4528  if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&
4529  (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&
4530  NextToken().is(tok::comma)) {
4531  // Parse optional reduction modifier.
4532  Data.ExtraModifier =
4533  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4534  Data.ExtraModifierLoc = Tok.getLocation();
4535  ConsumeToken();
4536  assert(Tok.is(tok::comma) && "Expected comma.");
4537  (void)ConsumeToken();
4538  }
4539  ColonProtectionRAIIObject ColonRAII(*this);
4540  if (getLangOpts().CPlusPlus)
4541  ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
4542  /*ObjectType=*/nullptr,
4543  /*ObjectHasErrors=*/false,
4544  /*EnteringContext=*/false);
4545  InvalidReductionId = ParseReductionId(
4546  *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4547  if (InvalidReductionId) {
4548  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4549  StopBeforeMatch);
4550  }
4551  if (Tok.is(tok::colon))
4552  Data.ColonLoc = ConsumeToken();
4553  else
4554  Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
4555  if (!InvalidReductionId)
4556  Data.ReductionOrMapperId =
4557  Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
4558  } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4559  if (getLangOpts().OpenMP >= 50) {
4560  if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4561  // Handle optional dependence modifier.
4562  // iterator(iterators-definition)
4563  // where iterators-definition is iterator-specifier [,
4564  // iterators-definition ]
4565  // where iterator-specifier is [ iterator-type ] identifier =
4566  // range-specification
4567  HasIterator = true;
4569  ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4570  Data.DepModOrTailExpr = IteratorRes.get();
4571  // Parse ','
4572  ExpectAndConsume(tok::comma);
4573  }
4574  }
4575  // Handle dependency type for depend clause.
4576  ColonProtectionRAIIObject ColonRAII(*this);
4577  Data.ExtraModifier = getOpenMPSimpleClauseType(
4578  Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4579  getLangOpts());
4580  Data.ExtraModifierLoc = Tok.getLocation();
4581  if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) ||
4582  (Kind == OMPC_doacross &&
4583  Data.ExtraModifier == OMPC_DOACROSS_unknown)) {
4584  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4585  StopBeforeMatch);
4586  } else {
4587  ConsumeToken();
4588  // Special processing for depend(source) clause.
4589  if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4590  Data.ExtraModifier == OMPC_DEPEND_source) {
4591  // Parse ')'.
4592  T.consumeClose();
4593  return false;
4594  }
4595  }
4596  if (Tok.is(tok::colon)) {
4597  Data.ColonLoc = ConsumeToken();
4598  } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
4599  Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4600  : diag::warn_pragma_expected_colon)
4601  << (Kind == OMPC_depend ? "dependency type" : "dependence-type");
4602  }
4603  if (Kind == OMPC_doacross) {
4604  if (Tok.is(tok::identifier) &&
4605  Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {
4606  Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source
4607  ? OMPC_DOACROSS_source_omp_cur_iteration
4608  : OMPC_DOACROSS_sink_omp_cur_iteration;
4609  ConsumeToken();
4610  }
4611  if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
4612  if (Tok.isNot(tok::minus)) {
4613  Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4614  << getOpenMPClauseName(Kind) << 0 << 0;
4615  SkipUntil(tok::r_paren);
4616  return false;
4617  } else {
4618  ConsumeToken();
4619  SourceLocation Loc = Tok.getLocation();
4620  uint64_t Value = 0;
4621  if (Tok.isNot(tok::numeric_constant) ||
4622  (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {
4623  Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
4624  << getOpenMPClauseName(Kind) << 0 << 0;
4625  SkipUntil(tok::r_paren);
4626  return false;
4627  }
4628  }
4629  }
4630  if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
4631  if (Tok.isNot(tok::r_paren)) {
4632  Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4633  << getOpenMPClauseName(Kind) << 1 << 1;
4634  SkipUntil(tok::r_paren);
4635  return false;
4636  }
4637  }
4638  // Only the 'sink' case has the expression list.
4639  if (Kind == OMPC_doacross &&
4640  (Data.ExtraModifier == OMPC_DOACROSS_source ||
4641  Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
4642  Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
4643  // Parse ')'.
4644  T.consumeClose();
4645  return false;
4646  }
4647  }
4648  } else if (Kind == OMPC_linear) {
4649  // Try to parse modifier if any.
4650  Data.ExtraModifier = OMPC_LINEAR_val;
4651  if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
4652  Data.ExtraModifier =
4653  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4654  Data.ExtraModifierLoc = ConsumeToken();
4655  LinearT.consumeOpen();
4656  NeedRParenForLinear = true;
4657  if (getLangOpts().OpenMP >= 52)
4658  Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
4659  << "linear-modifier(list)" << getOpenMPClauseName(Kind)
4660  << "linear(list: [linear-modifier,] step(step-size))";
4661  }
4662  } else if (Kind == OMPC_lastprivate) {
4663  // Try to parse modifier if any.
4664  Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
4665  // Conditional modifier allowed only in OpenMP 5.0 and not supported in
4666  // distribute and taskloop based directives.
4667  if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
4668  !isOpenMPTaskLoopDirective(DKind)) &&
4669  Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
4670  Data.ExtraModifier =
4671  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts());
4672  Data.ExtraModifierLoc = Tok.getLocation();
4673  ConsumeToken();
4674  assert(Tok.is(tok::colon) && "Expected colon.");
4675  Data.ColonLoc = ConsumeToken();
4676  }
4677  } else if (Kind == OMPC_map) {
4678  // Handle optional iterator map modifier.
4679  if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
4680  HasIterator = true;
4682  Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4683  Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
4684  ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4685  Data.IteratorExpr = IteratorRes.get();
4686  // Parse ','
4687  ExpectAndConsume(tok::comma);
4688  if (getLangOpts().OpenMP < 52) {
4689  Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4690  << (getLangOpts().OpenMP >= 51 ? 1 : 0)
4691  << getLangOpts().OpenMPExtensions;
4692  InvalidIterator = true;
4693  }
4694  }
4695  // Handle map type for map clause.
4696  ColonProtectionRAIIObject ColonRAII(*this);
4697 
4698  // The first identifier may be a list item, a map-type or a
4699  // map-type-modifier. The map-type can also be delete which has the same
4700  // spelling of the C++ delete keyword.
4701  Data.ExtraModifier = OMPC_MAP_unknown;
4702  Data.ExtraModifierLoc = Tok.getLocation();
4703 
4704  // Check for presence of a colon in the map clause.
4705  TentativeParsingAction TPA(*this);
4706  bool ColonPresent = false;
4707  if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4708  StopBeforeMatch)) {
4709  if (Tok.is(tok::colon))
4710  ColonPresent = true;
4711  }
4712  TPA.Revert();
4713  // Only parse map-type-modifier[s] and map-type if a colon is present in
4714  // the map clause.
4715  if (ColonPresent) {
4716  if (getLangOpts().OpenMP >= 60 && getCurToken().is(tok::colon))
4717  Diag(Tok, diag::err_omp_map_modifier_specification_list);
4718  IsInvalidMapperModifier = parseMapTypeModifiers(Data);
4719  if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
4720  parseMapType(*this, Data);
4721  else
4722  SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
4723  }
4724  if (Data.ExtraModifier == OMPC_MAP_unknown) {
4725  Data.ExtraModifier = OMPC_MAP_tofrom;
4726  if (getLangOpts().OpenMP >= 52) {
4727  if (DKind == OMPD_target_enter_data)
4728  Data.ExtraModifier = OMPC_MAP_to;
4729  else if (DKind == OMPD_target_exit_data)
4730  Data.ExtraModifier = OMPC_MAP_from;
4731  }
4732  Data.IsMapTypeImplicit = true;
4733  }
4734 
4735  if (Tok.is(tok::colon))
4736  Data.ColonLoc = ConsumeToken();
4737  } else if (Kind == OMPC_to || Kind == OMPC_from) {
4738  while (Tok.is(tok::identifier)) {
4739  auto Modifier = static_cast<OpenMPMotionModifierKind>(
4740  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()));
4741  if (Modifier == OMPC_MOTION_MODIFIER_unknown)
4742  break;
4743  Data.MotionModifiers.push_back(Modifier);
4744  Data.MotionModifiersLoc.push_back(Tok.getLocation());
4745  ConsumeToken();
4746  if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
4747  IsInvalidMapperModifier = parseMapperModifier(Data);
4748  if (IsInvalidMapperModifier)
4749  break;
4750  }
4751  // OpenMP < 5.1 doesn't permit a ',' or additional modifiers.
4752  if (getLangOpts().OpenMP < 51)
4753  break;
4754  // OpenMP 5.1 accepts an optional ',' even if the next character is ':'.
4755  // TODO: Is that intentional?
4756  if (Tok.is(tok::comma))
4757  ConsumeToken();
4758  }
4759  if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {
4760  if (!IsInvalidMapperModifier) {
4761  if (getLangOpts().OpenMP < 51)
4762  Diag(Tok, diag::warn_pragma_expected_colon) << ")";
4763  else
4764  Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";
4765  }
4766  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4767  StopBeforeMatch);
4768  }
4769  // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is
4770  // that intentional?
4771  if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&
4772  Tok.is(tok::colon))
4773  Data.ColonLoc = ConsumeToken();
4774  } else if (Kind == OMPC_allocate ||
4775  (Kind == OMPC_affinity && Tok.is(tok::identifier) &&
4776  PP.getSpelling(Tok) == "iterator")) {
4777  // Handle optional allocator expression followed by colon delimiter.
4778  ColonProtectionRAIIObject ColonRAII(*this);
4779  TentativeParsingAction TPA(*this);
4780  // OpenMP 5.0, 2.10.1, task Construct.
4781  // where aff-modifier is one of the following:
4782  // iterator(iterators-definition)
4783  ExprResult Tail;
4784  if (Kind == OMPC_allocate) {
4785  Tail = ParseAssignmentExpression();
4786  } else {
4787  HasIterator = true;
4789  Tail = ParseOpenMPIteratorsExpr();
4790  }
4791  Tail = Actions.CorrectDelayedTyposInExpr(Tail);
4792  Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
4793  /*DiscardedValue=*/false);
4794  if (Tail.isUsable()) {
4795  if (Tok.is(tok::colon)) {
4796  Data.DepModOrTailExpr = Tail.get();
4797  Data.ColonLoc = ConsumeToken();
4798  TPA.Commit();
4799  } else {
4800  // Colon not found, parse only list of variables.
4801  TPA.Revert();
4802  }
4803  } else {
4804  // Parsing was unsuccessfull, revert and skip to the end of clause or
4805  // directive.
4806  TPA.Revert();
4807  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4808  StopBeforeMatch);
4809  }
4810  } else if (Kind == OMPC_adjust_args) {
4811  // Handle adjust-op for adjust_args clause.
4812  ColonProtectionRAIIObject ColonRAII(*this);
4813  Data.ExtraModifier = getOpenMPSimpleClauseType(
4814  Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
4815  getLangOpts());
4816  Data.ExtraModifierLoc = Tok.getLocation();
4817  if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
4818  Diag(Tok, diag::err_omp_unknown_adjust_args_op);
4819  SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
4820  } else {
4821  ConsumeToken();
4822  if (Tok.is(tok::colon))
4823  Data.ColonLoc = Tok.getLocation();
4824  ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
4825  "adjust-op");
4826  }
4827  }
4828 
4829  bool IsComma =
4830  (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
4831  Kind != OMPC_in_reduction && Kind != OMPC_depend &&
4832  Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||
4833  (Kind == OMPC_reduction && !InvalidReductionId) ||
4834  (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
4835  (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
4836  (Kind == OMPC_doacross && Data.ExtraModifier != OMPC_DOACROSS_unknown) ||
4837  (Kind == OMPC_adjust_args &&
4838  Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
4839  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
4840  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
4841  Tok.isNot(tok::annot_pragma_openmp_end))) {
4842  ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
4843  ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
4844  if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) {
4845  // Parse variable
4846  ExprResult VarExpr =
4847  Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
4848  if (VarExpr.isUsable()) {
4849  Vars.push_back(VarExpr.get());
4850  } else {
4851  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4852  StopBeforeMatch);
4853  }
4854  }
4855  // Skip ',' if any
4856  IsComma = Tok.is(tok::comma);
4857  if (IsComma)
4858  ConsumeToken();
4859  else if (Tok.isNot(tok::r_paren) &&
4860  Tok.isNot(tok::annot_pragma_openmp_end) &&
4861  (!MayHaveTail || Tok.isNot(tok::colon)))
4862  Diag(Tok, diag::err_omp_expected_punc)
4863  << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
4864  : getOpenMPClauseName(Kind))
4865  << (Kind == OMPC_flush);
4866  }
4867 
4868  // Parse ')' for linear clause with modifier.
4869  if (NeedRParenForLinear)
4870  LinearT.consumeClose();
4871 
4872  // Parse ':' linear modifiers (val, uval, ref or step(step-size))
4873  // or parse ':' alignment.
4874  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
4875  bool StepFound = false;
4876  bool ModifierFound = false;
4877  if (MustHaveTail) {
4878  Data.ColonLoc = Tok.getLocation();
4879  SourceLocation ELoc = ConsumeToken();
4880 
4881  if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
4882  while (Tok.isNot(tok::r_paren)) {
4883  if (Tok.is(tok::identifier)) {
4884  // identifier could be a linear kind (val, uval, ref) or step
4885  // modifier or step size
4886  OpenMPLinearClauseKind LinKind =
4888  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
4889  getLangOpts()));
4890 
4891  if (LinKind == OMPC_LINEAR_step) {
4892  if (StepFound)
4893  Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
4894 
4895  BalancedDelimiterTracker StepT(*this, tok::l_paren,
4896  tok::annot_pragma_openmp_end);
4897  SourceLocation StepModifierLoc = ConsumeToken();
4898  // parse '('
4899  if (StepT.consumeOpen())
4900  Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";
4901 
4902  // parse step size expression
4903  StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4904  if (StepFound)
4905  Data.StepModifierLoc = StepModifierLoc;
4906 
4907  // parse ')'
4908  StepT.consumeClose();
4909  } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
4910  if (ModifierFound)
4911  Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
4912 
4913  Data.ExtraModifier = LinKind;
4914  Data.ExtraModifierLoc = ConsumeToken();
4915  ModifierFound = true;
4916  } else {
4917  StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4918  }
4919  } else {
4920  // parse an integer expression as step size
4921  StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());
4922  }
4923 
4924  if (Tok.is(tok::comma))
4925  ConsumeToken();
4926  if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))
4927  break;
4928  }
4929  if (!StepFound && !ModifierFound)
4930  Diag(ELoc, diag::err_expected_expression);
4931  } else {
4932  // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1)
4933  ExprResult Tail = ParseAssignmentExpression();
4934  Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,
4935  /*DiscardedValue*/ false);
4936  if (Tail.isUsable())
4937  Data.DepModOrTailExpr = Tail.get();
4938  else
4939  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4940  StopBeforeMatch);
4941  }
4942  }
4943 
4944  // Parse ')'.
4945  Data.RLoc = Tok.getLocation();
4946  if (!T.consumeClose())
4947  Data.RLoc = T.getCloseLocation();
4948  // Exit from scope when the iterator is used in depend clause.
4949  if (HasIterator)
4950  ExitScope();
4951  return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
4952  Vars.empty()) ||
4953  (MustHaveTail && !Data.DepModOrTailExpr && StepFound) ||
4954  InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
4955 }
4956 
4957 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
4958 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction',
4959 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'.
4960 ///
4961 /// private-clause:
4962 /// 'private' '(' list ')'
4963 /// firstprivate-clause:
4964 /// 'firstprivate' '(' list ')'
4965 /// lastprivate-clause:
4966 /// 'lastprivate' '(' list ')'
4967 /// shared-clause:
4968 /// 'shared' '(' list ')'
4969 /// linear-clause:
4970 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
4971 /// aligned-clause:
4972 /// 'aligned' '(' list [ ':' alignment ] ')'
4973 /// reduction-clause:
4974 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')'
4975 /// task_reduction-clause:
4976 /// 'task_reduction' '(' reduction-identifier ':' list ')'
4977 /// in_reduction-clause:
4978 /// 'in_reduction' '(' reduction-identifier ':' list ')'
4979 /// copyprivate-clause:
4980 /// 'copyprivate' '(' list ')'
4981 /// flush-clause:
4982 /// 'flush' '(' list ')'
4983 /// depend-clause:
4984 /// 'depend' '(' in | out | inout : list | source ')'
4985 /// map-clause:
4986 /// 'map' '(' [ [ always [,] ] [ close [,] ]
4987 /// [ mapper '(' mapper-identifier ')' [,] ]
4988 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
4989 /// to-clause:
4990 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
4991 /// from-clause:
4992 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
4993 /// use_device_ptr-clause:
4994 /// 'use_device_ptr' '(' list ')'
4995 /// use_device_addr-clause:
4996 /// 'use_device_addr' '(' list ')'
4997 /// is_device_ptr-clause:
4998 /// 'is_device_ptr' '(' list ')'
4999 /// has_device_addr-clause:
5000 /// 'has_device_addr' '(' list ')'
5001 /// allocate-clause:
5002 /// 'allocate' '(' [ allocator ':' ] list ')'
5003 /// nontemporal-clause:
5004 /// 'nontemporal' '(' list ')'
5005 /// inclusive-clause:
5006 /// 'inclusive' '(' list ')'
5007 /// exclusive-clause:
5008 /// 'exclusive' '(' list ')'
5009 ///
5010 /// For 'linear' clause linear-list may have the following forms:
5011 /// list
5012 /// modifier(list)
5013 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
5014 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
5016  bool ParseOnly) {
5017  SourceLocation Loc = Tok.getLocation();
5018  SourceLocation LOpen = ConsumeToken();
5021 
5022  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
5023  return nullptr;
5024 
5025  if (ParseOnly)
5026  return nullptr;
5027  OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
5028  return Actions.OpenMP().ActOnOpenMPVarListClause(Kind, Vars, Locs, Data);
5029 }
5030 
5031 bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,
5032  SourceLocation &ClauseNameLoc,
5033  SourceLocation &OpenLoc,
5034  SourceLocation &CloseLoc,
5035  SmallVectorImpl<Expr *> &Exprs,
5036  bool ReqIntConst) {
5037  assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&
5038  "Expected parsing to start at clause name");
5039  ClauseNameLoc = ConsumeToken();
5040 
5041  // Parse inside of '(' and ')'.
5042  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
5043  if (T.consumeOpen()) {
5044  Diag(Tok, diag::err_expected) << tok::l_paren;
5045  return true;
5046  }
5047 
5048  // Parse the list with interleaved commas.
5049  do {
5050  ExprResult Val =
5051  ReqIntConst ? ParseConstantExpression() : ParseAssignmentExpression();
5052  if (!Val.isUsable()) {
5053  // Encountered something other than an expression; abort to ')'.
5054  T.skipToEnd();
5055  return true;
5056  }
5057  Exprs.push_back(Val.get());
5058  } while (TryConsumeToken(tok::comma));
5059 
5060  bool Result = T.consumeClose();
5061  OpenLoc = T.getOpenLocation();
5062  CloseLoc = T.getCloseLocation();
5063  return Result;
5064 }
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3346
StringRef P
const Decl * D
enum clang::sema::@1659::IndirectLocalPathEntry::EntryKind Kind
Expr * E
llvm::APSInt APSInt
Definition: Compiler.cpp:22
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P)
static OpenMPMapModifierKind isMapModifier(Parser &P)
Checks if the token is a valid map-type-modifier.
static unsigned getOpenMPDirectiveKindEx(StringRef S)
static bool checkExtensionProperty(Parser &P, SourceLocation Loc, OMPTraitProperty &TIProperty, OMPTraitSelector &TISelector, llvm::StringMap< SourceLocation > &Seen)
static DeclarationName parseOpenMPReductionId(Parser &P)
static std::optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)
static ExprResult parseContextScore(Parser &P)
Parse optional 'score' '(' <expr> ')' ':'.
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, OpenMPClauseKind CKind, SourceLocation ELoc)
Parse step size expression.
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
static bool parseDeclareSimdClauses(Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, SmallVectorImpl< Expr * > &Uniforms, SmallVectorImpl< Expr * > &Aligneds, SmallVectorImpl< Expr * > &Alignments, SmallVectorImpl< Expr * > &Linears, SmallVectorImpl< unsigned > &LinModifiers, SmallVectorImpl< Expr * > &Steps)
Parses clauses for 'declare simd' directive.
static OpenMPMapClauseKind isMapType(Parser &P)
Checks if the token is a valid map-type.
This file declares semantic analysis functions specific to AMDGPU.
This file declares facilities that support code completion.
SourceRange Range
Definition: SemaObjC.cpp:758
SourceLocation Loc
Definition: SemaObjC.cpp:759
This file declares semantic analysis for OpenMP constructs and clauses.
const char * Data
This file defines OpenMP AST classes for executable directives and clauses.
Defines the clang::TokenKind enum and support functions.
SourceLocation End
SourceLocation Begin
VerifyDiagnosticConsumer::Directive Directive
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:664
OMPTraitInfo & getNewOMPTraitInfo()
Return a new OMPTraitInfo object owned by this context.
bool isUnset() const
Definition: Ownership.h:167
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
bool isEmpty() const
No scope specifier.
Definition: DeclSpec.h:208
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed.
Captures information about "declaration specifiers".
Definition: DeclSpec.h:247
static const TST TST_unspecified
Definition: DeclSpec.h:278
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition: DeclBase.h:1109
SourceLocation getLocation() const
Definition: DeclBase.h:446
DeclContext * getDeclContext()
Definition: DeclBase.h:455
The name of a declaration.
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1903
RAII object that enters a new expression evaluation context.
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition: Expr.h:239
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:480
This represents a decl that may have a name.
Definition: Decl.h:249
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition: Decl.cpp:1948
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
llvm::SmallVector< OMPTraitSet, 2 > Sets
The outermost level of selector sets.
Wrapper for void* pointer.
Definition: Ownership.h:50
PtrTy get() const
Definition: Ownership.h:80
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing,...
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
static const ParsedAttributesView & none()
Definition: ParsedAttr.h:843
ParsedAttributes - A collection of parsed attributes.
Definition: ParsedAttr.h:963
Introduces zero or more scopes for parsing.
Definition: Parser.h:1209
ParseScope - Introduces a new scope for parsing.
Definition: Parser.h:1171
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:58
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, SemaOpenMP::OpenMPVarListDataTy &Data)
Parses clauses with list.
bool parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses map-type-modifiers in map clause.
bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
Definition: Parser.h:1275
bool ParseOpenMPReservedLocator(OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data, const LangOptions &LangOpts)
Parses a reserved locator like 'omp_all_memory'.
A class for parsing a DeclSpec.
Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:137
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
A (possibly-)qualified type.
Definition: Type.h:941
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:1008
The collection of all-type qualifiers we support.
Definition: Type.h:319
Represents a struct/union/class.
Definition: Decl.h:4146
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
@ OpenMPDirectiveScope
This is the scope of OpenMP executable directive.
Definition: Scope.h:111
@ CompoundStmtScope
This is a compound statement scope.
Definition: Scope.h:134
@ OpenMPSimdDirectiveScope
This is the scope of some OpenMP simd directive.
Definition: Scope.h:119
@ FnScope
This indicates that the scope corresponds to a function, which means that labels are set here.
Definition: Scope.h:51
@ OpenMPLoopDirectiveScope
This is the scope of some OpenMP loop directive.
Definition: Scope.h:114
@ DeclScope
This is a scope that can contain a declaration.
Definition: Scope.h:63
Smart pointer class that efficiently represents Objective-C method names.
AMDGPUWavesPerEUAttr * CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
Definition: SemaAMDGPU.cpp:203
AMDGPUFlatWorkGroupSizeAttr * CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
Definition: SemaAMDGPU.cpp:142
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition: SemaOpenMP.h:111
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
Definition: SemaOpenMP.h:243
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition: SemaOpenMP.h:371
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition: Sema.h:8094
A RAII object to enter scope of a compound statement.
Definition: Sema.h:969
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:493
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
Definition: SemaExpr.cpp:20199
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
Definition: SemaExpr.cpp:17006
void ActOnReenterFunctionContext(Scope *S, Decl *D)
Push the parameters of D, which must be a function, into scope.
Definition: SemaDecl.cpp:1431
@ AllowFold
Definition: Sema.h:7286
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:763
DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef< Decl * > Group)
BuildDeclaratorGroup - convert a list of declarations into a declaration group, performing any necess...
Definition: SemaDecl.cpp:14917
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)
Retrieves the declaration name from a parsed unqualified-id.
Definition: SemaDecl.cpp:5835
SemaAMDGPU & AMDGPU()
Definition: Sema.h:1104
ASTContext & getASTContext() const
Definition: Sema.h:560
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:80
SemaOpenMP & OpenMP()
Definition: Sema.h:1184
CUDALaunchBoundsAttr * CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks)
Create an CUDALaunchBoundsAttr attribute.
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:417
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:8314
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1778
Token - This structure provides full information about a lexed token.
Definition: Token.h:36
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
Definition: Token.h:110
SourceLocation getEndLoc() const
Definition: Token.h:159
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Definition: Token.h:132
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition: Token.h:99
tok::TokenKind getKind() const
Definition: Token.h:94
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:187
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
Definition: Token.h:101
bool isNot(tok::TokenKind K) const
Definition: Token.h:100
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Definition: Token.h:121
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
The base class of the type hierarchy.
Definition: Type.h:1829
QualType getCanonicalTypeInternal() const
Definition: Type.h:2984
Represents a C++ unqualified-id that has been parsed.
Definition: DeclSpec.h:1028
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
Definition: DeclSpec.cpp:1510
QualType getType() const
Definition: Decl.h:679
Represents a variable declaration or definition.
Definition: Decl.h:880
Directive - Abstract class representing a parsed verify directive.
Defines the clang::TargetInfo interface.
constexpr XRayInstrMask None
Definition: XRayInstr.h:38
bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
Definition: Interp.h:275
bool Init(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1745
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
Definition: TokenKinds.h:89
The JSON file list parser is used to communicate input to InstallAPI.
TypeSpecifierType
Specifies the kind of type.
Definition: Specifiers.h:55
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
@ CPlusPlus
Definition: LangStandard.h:56
@ CPlusPlus11
Definition: LangStandard.h:57
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:24
@ OMPC_DEFAULTMAP_MODIFIER_unknown
Definition: OpenMPKinds.h:119
@ OMPC_ORDER_MODIFIER_unknown
Definition: OpenMPKinds.h:172
@ OMPC_ADJUST_ARGS_unknown
Definition: OpenMPKinds.h:196
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ OMPC_REDUCTION_unknown
Definition: OpenMPKinds.h:189
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition: CallGraph.h:223
OpenMPDeviceType
OpenMP device type for 'device_type' clause.
Definition: OpenMPKinds.h:149
@ OMPC_DEVICE_TYPE_unknown
Definition: OpenMPKinds.h:153
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition: OpenMPKinds.h:39
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:27
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ OMPC_DOACROSS_unknown
Definition: OpenMPKinds.h:222
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
StmtResult StmtError()
Definition: Ownership.h:265
DeclaratorContext
Definition: DeclSpec.h:1853
@ Property
The type of a property.
@ OMPC_LASTPRIVATE_unknown
Definition: OpenMPKinds.h:160
@ OMPC_DEPEND_unknown
Definition: OpenMPKinds.h:58
OpenMPGrainsizeClauseModifier
Definition: OpenMPKinds.h:206
@ OMPC_GRAINSIZE_unknown
Definition: OpenMPKinds.h:209
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts)
OpenMPNumTasksClauseModifier
Definition: OpenMPKinds.h:212
@ OMPC_NUMTASKS_unknown
Definition: OpenMPKinds.h:215
ActionResult< Expr * > ExprResult
Definition: Ownership.h:248
ExprResult ExprError()
Definition: Ownership.h:264
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition: OpenMPKinds.h:91
@ OMPC_MOTION_MODIFIER_unknown
Definition: OpenMPKinds.h:95
bool operator!=(CanQual< T > x, CanQual< U > y)
ActionResult< Stmt * > StmtResult
Definition: Ownership.h:249
@ OMPC_DEFAULTMAP_unknown
Definition: OpenMPKinds.h:114
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition: OpenMPKinds.h:62
@ OMPC_LINEAR_unknown
Definition: OpenMPKinds.h:66
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
const FunctionProtoType * T
StmtResult StmtEmpty()
Definition: Ownership.h:272
@ OMPC_DEVICE_unknown
Definition: OpenMPKinds.h:50
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition: OpenMPKinds.h:78
@ OMPC_MAP_MODIFIER_unknown
Definition: OpenMPKinds.h:79
@ OMPC_ORDER_unknown
Definition: OpenMPKinds.h:167
@ OMPC_SCHEDULE_unknown
Definition: OpenMPKinds.h:34
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:123
@ AS_none
Definition: Specifiers.h:127
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition: OpenMPKinds.h:70
@ OMPC_MAP_unknown
Definition: OpenMPKinds.h:74
unsigned long uint64_t
#define false
Definition: stdbool.h:26
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:232
llvm::omp::TraitProperty Kind
StringRef RawString
The raw string as we parsed it.
llvm::omp::TraitSelector Kind
llvm::SmallVector< OMPTraitProperty, 1 > Properties
llvm::omp::TraitSet Kind
llvm::SmallVector< OMPTraitSelector, 2 > Selectors
This structure contains most locations needed for by an OMPVarListClause.
Definition: OpenMPClause.h:259
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition: SemaOpenMP.h:316
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition: SemaOpenMP.h:313
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition: SemaOpenMP.h:310
SourceLocation Loc
The directive location.
Definition: SemaOpenMP.h:319
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition: SemaOpenMP.h:307
Data structure for iterator expression.
Definition: SemaOpenMP.h:1381
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1125
Data for list of allocators.
Definition: SemaOpenMP.h:1321
Clang specific specialization of the OMPContext to lookup target features.