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