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