clang  6.0.0
ParseOpenMP.cpp
Go to the documentation of this file.
1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// \brief This file implements parsing of all OpenMP directives and clauses.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/StmtOpenMP.h"
17 #include "clang/Parse/Parser.h"
19 #include "clang/Sema/Scope.h"
20 #include "llvm/ADT/PointerIntPair.h"
21 
22 using namespace clang;
23 
24 //===----------------------------------------------------------------------===//
25 // OpenMP declarative directives.
26 //===----------------------------------------------------------------------===//
27 
28 namespace {
30  OMPD_cancellation = OMPD_unknown + 1,
31  OMPD_data,
32  OMPD_declare,
33  OMPD_end,
34  OMPD_end_declare,
35  OMPD_enter,
36  OMPD_exit,
37  OMPD_point,
38  OMPD_reduction,
39  OMPD_target_enter,
40  OMPD_target_exit,
41  OMPD_update,
42  OMPD_distribute_parallel,
43  OMPD_teams_distribute_parallel,
44  OMPD_target_teams_distribute_parallel
45 };
46 
47 class ThreadprivateListParserHelper final {
48  SmallVector<Expr *, 4> Identifiers;
49  Parser *P;
50 
51 public:
52  ThreadprivateListParserHelper(Parser *P) : P(P) {}
53  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
54  ExprResult Res =
55  P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo);
56  if (Res.isUsable())
57  Identifiers.push_back(Res.get());
58  }
59  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
60 };
61 } // namespace
62 
63 // Map token string to extended OMP token kind that are
64 // OpenMPDirectiveKind + OpenMPDirectiveKindEx.
65 static unsigned getOpenMPDirectiveKindEx(StringRef S) {
66  auto DKind = getOpenMPDirectiveKind(S);
67  if (DKind != OMPD_unknown)
68  return DKind;
69 
70  return llvm::StringSwitch<unsigned>(S)
71  .Case("cancellation", OMPD_cancellation)
72  .Case("data", OMPD_data)
73  .Case("declare", OMPD_declare)
74  .Case("end", OMPD_end)
75  .Case("enter", OMPD_enter)
76  .Case("exit", OMPD_exit)
77  .Case("point", OMPD_point)
78  .Case("reduction", OMPD_reduction)
79  .Case("update", OMPD_update)
80  .Default(OMPD_unknown);
81 }
82 
84  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
85  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
86  // TODO: add other combined directives in topological order.
87  static const unsigned F[][3] = {
88  { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
89  { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
90  { OMPD_declare, OMPD_simd, OMPD_declare_simd },
91  { OMPD_declare, OMPD_target, OMPD_declare_target },
92  { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
93  { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
94  { OMPD_distribute_parallel_for, OMPD_simd,
95  OMPD_distribute_parallel_for_simd },
96  { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
97  { OMPD_end, OMPD_declare, OMPD_end_declare },
98  { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
99  { OMPD_target, OMPD_data, OMPD_target_data },
100  { OMPD_target, OMPD_enter, OMPD_target_enter },
101  { OMPD_target, OMPD_exit, OMPD_target_exit },
102  { OMPD_target, OMPD_update, OMPD_target_update },
103  { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
104  { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
105  { OMPD_for, OMPD_simd, OMPD_for_simd },
106  { OMPD_parallel, OMPD_for, OMPD_parallel_for },
107  { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
108  { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
109  { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
110  { OMPD_target, OMPD_parallel, OMPD_target_parallel },
111  { OMPD_target, OMPD_simd, OMPD_target_simd },
112  { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
113  { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd },
114  { OMPD_teams, OMPD_distribute, OMPD_teams_distribute },
115  { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd },
116  { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel },
117  { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for },
118  { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd },
119  { OMPD_target, OMPD_teams, OMPD_target_teams },
120  { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute },
121  { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel },
122  { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
123  { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
124  { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
125  };
126  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
127  auto Tok = P.getCurToken();
128  unsigned DKind =
129  Tok.isAnnotation()
130  ? static_cast<unsigned>(OMPD_unknown)
132  if (DKind == OMPD_unknown)
133  return OMPD_unknown;
134 
135  for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
136  if (DKind != F[i][0])
137  continue;
138 
139  Tok = P.getPreprocessor().LookAhead(0);
140  unsigned SDKind =
141  Tok.isAnnotation()
142  ? static_cast<unsigned>(OMPD_unknown)
144  if (SDKind == OMPD_unknown)
145  continue;
146 
147  if (SDKind == F[i][1]) {
148  P.ConsumeToken();
149  DKind = F[i][2];
150  }
151  }
152  return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
153  : OMPD_unknown;
154 }
155 
157  Token Tok = P.getCurToken();
158  Sema &Actions = P.getActions();
160  // Allow to use 'operator' keyword for C++ operators
161  bool WithOperator = false;
162  if (Tok.is(tok::kw_operator)) {
163  P.ConsumeToken();
164  Tok = P.getCurToken();
165  WithOperator = true;
166  }
167  switch (Tok.getKind()) {
168  case tok::plus: // '+'
169  OOK = OO_Plus;
170  break;
171  case tok::minus: // '-'
172  OOK = OO_Minus;
173  break;
174  case tok::star: // '*'
175  OOK = OO_Star;
176  break;
177  case tok::amp: // '&'
178  OOK = OO_Amp;
179  break;
180  case tok::pipe: // '|'
181  OOK = OO_Pipe;
182  break;
183  case tok::caret: // '^'
184  OOK = OO_Caret;
185  break;
186  case tok::ampamp: // '&&'
187  OOK = OO_AmpAmp;
188  break;
189  case tok::pipepipe: // '||'
190  OOK = OO_PipePipe;
191  break;
192  case tok::identifier: // identifier
193  if (!WithOperator)
194  break;
195  LLVM_FALLTHROUGH;
196  default:
197  P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
198  P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
200  return DeclarationName();
201  }
202  P.ConsumeToken();
203  auto &DeclNames = Actions.getASTContext().DeclarationNames;
204  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
205  : DeclNames.getCXXOperatorName(OOK);
206 }
207 
208 /// \brief Parse 'omp declare reduction' construct.
209 ///
210 /// declare-reduction-directive:
211 /// annot_pragma_openmp 'declare' 'reduction'
212 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
213 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
214 /// annot_pragma_openmp_end
215 /// <reduction_id> is either a base language identifier or one of the following
216 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
217 ///
219 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
220  // Parse '('.
221  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
222  if (T.expectAndConsume(diag::err_expected_lparen_after,
223  getOpenMPDirectiveName(OMPD_declare_reduction))) {
224  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
225  return DeclGroupPtrTy();
226  }
227 
229  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
230  return DeclGroupPtrTy();
231 
232  // Consume ':'.
233  bool IsCorrect = !ExpectAndConsume(tok::colon);
234 
235  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
236  return DeclGroupPtrTy();
237 
238  IsCorrect = IsCorrect && !Name.isEmpty();
239 
240  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
241  Diag(Tok.getLocation(), diag::err_expected_type);
242  IsCorrect = false;
243  }
244 
245  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
246  return DeclGroupPtrTy();
247 
249  // Parse list of types until ':' token.
250  do {
251  ColonProtectionRAIIObject ColonRAII(*this);
252  SourceRange Range;
253  TypeResult TR =
254  ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
255  if (TR.isUsable()) {
256  auto ReductionType =
257  Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
258  if (!ReductionType.isNull()) {
259  ReductionTypes.push_back(
260  std::make_pair(ReductionType, Range.getBegin()));
261  }
262  } else {
263  SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
264  StopBeforeMatch);
265  }
266 
267  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
268  break;
269 
270  // Consume ','.
271  if (ExpectAndConsume(tok::comma)) {
272  IsCorrect = false;
273  if (Tok.is(tok::annot_pragma_openmp_end)) {
274  Diag(Tok.getLocation(), diag::err_expected_type);
275  return DeclGroupPtrTy();
276  }
277  }
278  } while (Tok.isNot(tok::annot_pragma_openmp_end));
279 
280  if (ReductionTypes.empty()) {
281  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
282  return DeclGroupPtrTy();
283  }
284 
285  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
286  return DeclGroupPtrTy();
287 
288  // Consume ':'.
289  if (ExpectAndConsume(tok::colon))
290  IsCorrect = false;
291 
292  if (Tok.is(tok::annot_pragma_openmp_end)) {
293  Diag(Tok.getLocation(), diag::err_expected_expression);
294  return DeclGroupPtrTy();
295  }
296 
297  DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
298  getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
299 
300  // Parse <combiner> expression and then parse initializer if any for each
301  // correct type.
302  unsigned I = 0, E = ReductionTypes.size();
303  for (auto *D : DRD.get()) {
304  TentativeParsingAction TPA(*this);
305  ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
308  // Parse <combiner> expression.
309  Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
310  ExprResult CombinerResult =
311  Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
312  D->getLocation(), /*DiscardedValue=*/true);
313  Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
314 
315  if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
316  Tok.isNot(tok::annot_pragma_openmp_end)) {
317  TPA.Commit();
318  IsCorrect = false;
319  break;
320  }
321  IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
322  ExprResult InitializerResult;
323  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
324  // Parse <initializer> expression.
325  if (Tok.is(tok::identifier) &&
326  Tok.getIdentifierInfo()->isStr("initializer"))
327  ConsumeToken();
328  else {
329  Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
330  TPA.Commit();
331  IsCorrect = false;
332  break;
333  }
334  // Parse '('.
335  BalancedDelimiterTracker T(*this, tok::l_paren,
336  tok::annot_pragma_openmp_end);
337  IsCorrect =
338  !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
339  IsCorrect;
340  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
341  ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
344  // Parse expression.
345  VarDecl *OmpPrivParm =
346  Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
347  D);
348  // Check if initializer is omp_priv <init_expr> or something else.
349  if (Tok.is(tok::identifier) &&
350  Tok.getIdentifierInfo()->isStr("omp_priv")) {
351  ConsumeToken();
352  ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
353  } else {
354  InitializerResult = Actions.ActOnFinishFullExpr(
355  ParseAssignmentExpression().get(), D->getLocation(),
356  /*DiscardedValue=*/true);
357  }
358  Actions.ActOnOpenMPDeclareReductionInitializerEnd(
359  D, InitializerResult.get(), OmpPrivParm);
360  if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
361  Tok.isNot(tok::annot_pragma_openmp_end)) {
362  TPA.Commit();
363  IsCorrect = false;
364  break;
365  }
366  IsCorrect =
367  !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
368  }
369  }
370 
371  ++I;
372  // Revert parsing if not the last type, otherwise accept it, we're done with
373  // parsing.
374  if (I != E)
375  TPA.Revert();
376  else
377  TPA.Commit();
378  }
379  return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
380  IsCorrect);
381 }
382 
383 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
384  // Parse declarator '=' initializer.
385  // If a '==' or '+=' is found, suggest a fixit to '='.
386  if (isTokenEqualOrEqualTypo()) {
387  ConsumeToken();
388 
389  if (Tok.is(tok::code_completion)) {
390  Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
391  Actions.FinalizeDeclaration(OmpPrivParm);
392  cutOffParsing();
393  return;
394  }
395 
396  ExprResult Init(ParseInitializer());
397 
398  if (Init.isInvalid()) {
399  SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
400  Actions.ActOnInitializerError(OmpPrivParm);
401  } else {
402  Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
403  /*DirectInit=*/false);
404  }
405  } else if (Tok.is(tok::l_paren)) {
406  // Parse C++ direct initializer: '(' expression-list ')'
407  BalancedDelimiterTracker T(*this, tok::l_paren);
408  T.consumeOpen();
409 
410  ExprVector Exprs;
411  CommaLocsTy CommaLocs;
412 
413  if (ParseExpressionList(Exprs, CommaLocs, [this, OmpPrivParm, &Exprs] {
414  Actions.CodeCompleteConstructor(
415  getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
416  OmpPrivParm->getLocation(), Exprs);
417  })) {
418  Actions.ActOnInitializerError(OmpPrivParm);
419  SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
420  } else {
421  // Match the ')'.
422  T.consumeClose();
423 
424  assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
425  "Unexpected number of commas!");
426 
427  ExprResult Initializer = Actions.ActOnParenListExpr(
428  T.getOpenLocation(), T.getCloseLocation(), Exprs);
429  Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
430  /*DirectInit=*/true);
431  }
432  } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
433  // Parse C++0x braced-init-list.
434  Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
435 
436  ExprResult Init(ParseBraceInitializer());
437 
438  if (Init.isInvalid()) {
439  Actions.ActOnInitializerError(OmpPrivParm);
440  } else {
441  Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
442  /*DirectInit=*/true);
443  }
444  } else {
445  Actions.ActOnUninitializedDecl(OmpPrivParm);
446  }
447 }
448 
449 namespace {
450 /// RAII that recreates function context for correct parsing of clauses of
451 /// 'declare simd' construct.
452 /// OpenMP, 2.8.2 declare simd Construct
453 /// The expressions appearing in the clauses of this directive are evaluated in
454 /// the scope of the arguments of the function declaration or definition.
455 class FNContextRAII final {
456  Parser &P;
457  Sema::CXXThisScopeRAII *ThisScope;
458  Parser::ParseScope *TempScope;
459  Parser::ParseScope *FnScope;
460  bool HasTemplateScope = false;
461  bool HasFunScope = false;
462  FNContextRAII() = delete;
463  FNContextRAII(const FNContextRAII &) = delete;
464  FNContextRAII &operator=(const FNContextRAII &) = delete;
465 
466 public:
467  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
468  Decl *D = *Ptr.get().begin();
469  NamedDecl *ND = dyn_cast<NamedDecl>(D);
470  RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
471  Sema &Actions = P.getActions();
472 
473  // Allow 'this' within late-parsed attributes.
474  ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
475  ND && ND->isCXXInstanceMember());
476 
477  // If the Decl is templatized, add template parameters to scope.
478  HasTemplateScope = D->isTemplateDecl();
479  TempScope =
480  new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
481  if (HasTemplateScope)
482  Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
483 
484  // If the Decl is on a function, add function parameters to the scope.
485  HasFunScope = D->isFunctionOrFunctionTemplate();
486  FnScope = new Parser::ParseScope(
488  HasFunScope);
489  if (HasFunScope)
490  Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
491  }
492  ~FNContextRAII() {
493  if (HasFunScope) {
495  FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
496  }
497  if (HasTemplateScope)
498  TempScope->Exit();
499  delete FnScope;
500  delete TempScope;
501  delete ThisScope;
502  }
503 };
504 } // namespace
505 
506 /// Parses clauses for 'declare simd' directive.
507 /// clause:
508 /// 'inbranch' | 'notinbranch'
509 /// 'simdlen' '(' <expr> ')'
510 /// { 'uniform' '(' <argument_list> ')' }
511 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
512 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
514  Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
516  SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
517  SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
518  SourceRange BSRange;
519  const Token &Tok = P.getCurToken();
520  bool IsError = false;
521  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
522  if (Tok.isNot(tok::identifier))
523  break;
524  OMPDeclareSimdDeclAttr::BranchStateTy Out;
525  IdentifierInfo *II = Tok.getIdentifierInfo();
526  StringRef ClauseName = II->getName();
527  // Parse 'inranch|notinbranch' clauses.
528  if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
529  if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
530  P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
531  << ClauseName
532  << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
533  IsError = true;
534  }
535  BS = Out;
536  BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
537  P.ConsumeToken();
538  } else if (ClauseName.equals("simdlen")) {
539  if (SimdLen.isUsable()) {
540  P.Diag(Tok, diag::err_omp_more_one_clause)
541  << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
542  IsError = true;
543  }
544  P.ConsumeToken();
545  SourceLocation RLoc;
546  SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
547  if (SimdLen.isInvalid())
548  IsError = true;
549  } else {
550  OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
551  if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
552  CKind == OMPC_linear) {
554  auto *Vars = &Uniforms;
555  if (CKind == OMPC_aligned)
556  Vars = &Aligneds;
557  else if (CKind == OMPC_linear)
558  Vars = &Linears;
559 
560  P.ConsumeToken();
561  if (P.ParseOpenMPVarList(OMPD_declare_simd,
562  getOpenMPClauseKind(ClauseName), *Vars, Data))
563  IsError = true;
564  if (CKind == OMPC_aligned)
565  Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
566  else if (CKind == OMPC_linear) {
568  Data.DepLinMapLoc))
569  Data.LinKind = OMPC_LINEAR_val;
570  LinModifiers.append(Linears.size() - LinModifiers.size(),
571  Data.LinKind);
572  Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
573  }
574  } else
575  // TODO: add parsing of other clauses.
576  break;
577  }
578  // Skip ',' if any.
579  if (Tok.is(tok::comma))
580  P.ConsumeToken();
581  }
582  return IsError;
583 }
584 
585 /// Parse clauses for '#pragma omp declare simd'.
587 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
588  CachedTokens &Toks, SourceLocation Loc) {
589  PP.EnterToken(Tok);
590  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
591  // Consume the previously pushed token.
592  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
593 
594  FNContextRAII FnContext(*this, Ptr);
595  OMPDeclareSimdDeclAttr::BranchStateTy BS =
596  OMPDeclareSimdDeclAttr::BS_Undefined;
597  ExprResult Simdlen;
598  SmallVector<Expr *, 4> Uniforms;
599  SmallVector<Expr *, 4> Aligneds;
600  SmallVector<Expr *, 4> Alignments;
601  SmallVector<Expr *, 4> Linears;
602  SmallVector<unsigned, 4> LinModifiers;
604  bool IsError =
605  parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
606  Alignments, Linears, LinModifiers, Steps);
607  // Need to check for extra tokens.
608  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
609  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
610  << getOpenMPDirectiveName(OMPD_declare_simd);
611  while (Tok.isNot(tok::annot_pragma_openmp_end))
612  ConsumeAnyToken();
613  }
614  // Skip the last annot_pragma_openmp_end.
615  SourceLocation EndLoc = ConsumeAnnotationToken();
616  if (!IsError) {
617  return Actions.ActOnOpenMPDeclareSimdDirective(
618  Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
619  LinModifiers, Steps, SourceRange(Loc, EndLoc));
620  }
621  return Ptr;
622 }
623 
624 /// \brief Parsing of declarative OpenMP directives.
625 ///
626 /// threadprivate-directive:
627 /// annot_pragma_openmp 'threadprivate' simple-variable-list
628 /// annot_pragma_openmp_end
629 ///
630 /// declare-reduction-directive:
631 /// annot_pragma_openmp 'declare' 'reduction' [...]
632 /// annot_pragma_openmp_end
633 ///
634 /// declare-simd-directive:
635 /// annot_pragma_openmp 'declare simd' {<clause> [,]}
636 /// annot_pragma_openmp_end
637 /// <function declaration/definition>
638 ///
639 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
640  AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
641  DeclSpec::TST TagType, Decl *Tag) {
642  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
643  ParenBraceBracketBalancer BalancerRAIIObj(*this);
644 
645  SourceLocation Loc = ConsumeAnnotationToken();
646  auto DKind = ParseOpenMPDirectiveKind(*this);
647 
648  switch (DKind) {
649  case OMPD_threadprivate: {
650  ConsumeToken();
651  ThreadprivateListParserHelper Helper(this);
652  if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
653  // The last seen token is annot_pragma_openmp_end - need to check for
654  // extra tokens.
655  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
656  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
657  << getOpenMPDirectiveName(OMPD_threadprivate);
658  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
659  }
660  // Skip the last annot_pragma_openmp_end.
661  ConsumeAnnotationToken();
662  return Actions.ActOnOpenMPThreadprivateDirective(Loc,
663  Helper.getIdentifiers());
664  }
665  break;
666  }
667  case OMPD_declare_reduction:
668  ConsumeToken();
669  if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
670  // The last seen token is annot_pragma_openmp_end - need to check for
671  // extra tokens.
672  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
673  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
674  << getOpenMPDirectiveName(OMPD_declare_reduction);
675  while (Tok.isNot(tok::annot_pragma_openmp_end))
676  ConsumeAnyToken();
677  }
678  // Skip the last annot_pragma_openmp_end.
679  ConsumeAnnotationToken();
680  return Res;
681  }
682  break;
683  case OMPD_declare_simd: {
684  // The syntax is:
685  // { #pragma omp declare simd }
686  // <function-declaration-or-definition>
687  //
688  ConsumeToken();
689  CachedTokens Toks;
690  while(Tok.isNot(tok::annot_pragma_openmp_end)) {
691  Toks.push_back(Tok);
692  ConsumeAnyToken();
693  }
694  Toks.push_back(Tok);
695  ConsumeAnyToken();
696 
697  DeclGroupPtrTy Ptr;
698  if (Tok.is(tok::annot_pragma_openmp))
699  Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
700  else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
701  // Here we expect to see some function declaration.
702  if (AS == AS_none) {
704  MaybeParseCXX11Attributes(Attrs);
705  ParsingDeclSpec PDS(*this);
706  Ptr = ParseExternalDeclaration(Attrs, &PDS);
707  } else {
708  Ptr =
709  ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
710  }
711  }
712  if (!Ptr) {
713  Diag(Loc, diag::err_omp_decl_in_declare_simd);
714  return DeclGroupPtrTy();
715  }
716  return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
717  }
718  case OMPD_declare_target: {
719  SourceLocation DTLoc = ConsumeAnyToken();
720  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
721  // OpenMP 4.5 syntax with list of entities.
723  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
724  OMPDeclareTargetDeclAttr::MapTypeTy MT =
725  OMPDeclareTargetDeclAttr::MT_To;
726  if (Tok.is(tok::identifier)) {
727  IdentifierInfo *II = Tok.getIdentifierInfo();
728  StringRef ClauseName = II->getName();
729  // Parse 'to|link' clauses.
730  if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
731  MT)) {
732  Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
733  << ClauseName;
734  break;
735  }
736  ConsumeToken();
737  }
738  auto Callback = [this, MT, &SameDirectiveDecls](
739  CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
740  Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
741  SameDirectiveDecls);
742  };
743  if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
744  break;
745 
746  // Consume optional ','.
747  if (Tok.is(tok::comma))
748  ConsumeToken();
749  }
750  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
751  ConsumeAnyToken();
752  return DeclGroupPtrTy();
753  }
754 
755  // Skip the last annot_pragma_openmp_end.
756  ConsumeAnyToken();
757 
758  if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
759  return DeclGroupPtrTy();
760 
761  DKind = ParseOpenMPDirectiveKind(*this);
762  while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
763  Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
764  DeclGroupPtrTy Ptr;
765  // Here we expect to see some function declaration.
766  if (AS == AS_none) {
768  MaybeParseCXX11Attributes(Attrs);
769  ParsingDeclSpec PDS(*this);
770  Ptr = ParseExternalDeclaration(Attrs, &PDS);
771  } else {
772  Ptr =
773  ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
774  }
775  if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
776  TentativeParsingAction TPA(*this);
777  ConsumeAnnotationToken();
778  DKind = ParseOpenMPDirectiveKind(*this);
779  if (DKind != OMPD_end_declare_target)
780  TPA.Revert();
781  else
782  TPA.Commit();
783  }
784  }
785 
786  if (DKind == OMPD_end_declare_target) {
787  ConsumeAnyToken();
788  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
789  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
790  << getOpenMPDirectiveName(OMPD_end_declare_target);
791  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
792  }
793  // Skip the last annot_pragma_openmp_end.
794  ConsumeAnyToken();
795  } else {
796  Diag(Tok, diag::err_expected_end_declare_target);
797  Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
798  }
799  Actions.ActOnFinishOpenMPDeclareTargetDirective();
800  return DeclGroupPtrTy();
801  }
802  case OMPD_unknown:
803  Diag(Tok, diag::err_omp_unknown_directive);
804  break;
805  case OMPD_parallel:
806  case OMPD_simd:
807  case OMPD_task:
808  case OMPD_taskyield:
809  case OMPD_barrier:
810  case OMPD_taskwait:
811  case OMPD_taskgroup:
812  case OMPD_flush:
813  case OMPD_for:
814  case OMPD_for_simd:
815  case OMPD_sections:
816  case OMPD_section:
817  case OMPD_single:
818  case OMPD_master:
819  case OMPD_ordered:
820  case OMPD_critical:
821  case OMPD_parallel_for:
822  case OMPD_parallel_for_simd:
823  case OMPD_parallel_sections:
824  case OMPD_atomic:
825  case OMPD_target:
826  case OMPD_teams:
827  case OMPD_cancellation_point:
828  case OMPD_cancel:
829  case OMPD_target_data:
830  case OMPD_target_enter_data:
831  case OMPD_target_exit_data:
832  case OMPD_target_parallel:
833  case OMPD_target_parallel_for:
834  case OMPD_taskloop:
835  case OMPD_taskloop_simd:
836  case OMPD_distribute:
837  case OMPD_end_declare_target:
838  case OMPD_target_update:
839  case OMPD_distribute_parallel_for:
840  case OMPD_distribute_parallel_for_simd:
841  case OMPD_distribute_simd:
842  case OMPD_target_parallel_for_simd:
843  case OMPD_target_simd:
844  case OMPD_teams_distribute:
845  case OMPD_teams_distribute_simd:
846  case OMPD_teams_distribute_parallel_for_simd:
847  case OMPD_teams_distribute_parallel_for:
848  case OMPD_target_teams:
849  case OMPD_target_teams_distribute:
850  case OMPD_target_teams_distribute_parallel_for:
851  case OMPD_target_teams_distribute_parallel_for_simd:
852  case OMPD_target_teams_distribute_simd:
853  Diag(Tok, diag::err_omp_unexpected_directive)
854  << getOpenMPDirectiveName(DKind);
855  break;
856  }
857  while (Tok.isNot(tok::annot_pragma_openmp_end))
858  ConsumeAnyToken();
859  ConsumeAnyToken();
860  return nullptr;
861 }
862 
863 /// \brief Parsing of declarative or executable OpenMP directives.
864 ///
865 /// threadprivate-directive:
866 /// annot_pragma_openmp 'threadprivate' simple-variable-list
867 /// annot_pragma_openmp_end
868 ///
869 /// declare-reduction-directive:
870 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
871 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
872 /// ('omp_priv' '=' <expression>|<function_call>) ')']
873 /// annot_pragma_openmp_end
874 ///
875 /// executable-directive:
876 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
877 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
878 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
879 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
880 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
881 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
882 /// 'distribute' | 'target enter data' | 'target exit data' |
883 /// 'target parallel' | 'target parallel for' |
884 /// 'target update' | 'distribute parallel for' |
885 /// 'distribute paralle for simd' | 'distribute simd' |
886 /// 'target parallel for simd' | 'target simd' |
887 /// 'teams distribute' | 'teams distribute simd' |
888 /// 'teams distribute parallel for simd' |
889 /// 'teams distribute parallel for' | 'target teams' |
890 /// 'target teams distribute' |
891 /// 'target teams distribute parallel for' |
892 /// 'target teams distribute parallel for simd' |
893 /// 'target teams distribute simd' {clause}
894 /// annot_pragma_openmp_end
895 ///
896 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
897  AllowedConstructsKind Allowed) {
898  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
899  ParenBraceBracketBalancer BalancerRAIIObj(*this);
902  FirstClauses(OMPC_unknown + 1);
903  unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
905  SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
906  auto DKind = ParseOpenMPDirectiveKind(*this);
907  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
908  // Name of critical directive.
909  DeclarationNameInfo DirName;
911  bool HasAssociatedStatement = true;
912  bool FlushHasClause = false;
913 
914  switch (DKind) {
915  case OMPD_threadprivate: {
916  if (Allowed != ACK_Any) {
917  Diag(Tok, diag::err_omp_immediate_directive)
918  << getOpenMPDirectiveName(DKind) << 0;
919  }
920  ConsumeToken();
921  ThreadprivateListParserHelper Helper(this);
922  if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
923  // The last seen token is annot_pragma_openmp_end - need to check for
924  // extra tokens.
925  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
926  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
927  << getOpenMPDirectiveName(OMPD_threadprivate);
928  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
929  }
930  DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
931  Loc, Helper.getIdentifiers());
932  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
933  }
934  SkipUntil(tok::annot_pragma_openmp_end);
935  break;
936  }
937  case OMPD_declare_reduction:
938  ConsumeToken();
939  if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
940  // The last seen token is annot_pragma_openmp_end - need to check for
941  // extra tokens.
942  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
943  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
944  << getOpenMPDirectiveName(OMPD_declare_reduction);
945  while (Tok.isNot(tok::annot_pragma_openmp_end))
946  ConsumeAnyToken();
947  }
948  ConsumeAnyToken();
949  Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
950  } else
951  SkipUntil(tok::annot_pragma_openmp_end);
952  break;
953  case OMPD_flush:
954  if (PP.LookAhead(0).is(tok::l_paren)) {
955  FlushHasClause = true;
956  // Push copy of the current token back to stream to properly parse
957  // pseudo-clause OMPFlushClause.
958  PP.EnterToken(Tok);
959  }
960  LLVM_FALLTHROUGH;
961  case OMPD_taskyield:
962  case OMPD_barrier:
963  case OMPD_taskwait:
964  case OMPD_cancellation_point:
965  case OMPD_cancel:
966  case OMPD_target_enter_data:
967  case OMPD_target_exit_data:
968  case OMPD_target_update:
969  if (Allowed == ACK_StatementsOpenMPNonStandalone) {
970  Diag(Tok, diag::err_omp_immediate_directive)
971  << getOpenMPDirectiveName(DKind) << 0;
972  }
973  HasAssociatedStatement = false;
974  // Fall through for further analysis.
975  LLVM_FALLTHROUGH;
976  case OMPD_parallel:
977  case OMPD_simd:
978  case OMPD_for:
979  case OMPD_for_simd:
980  case OMPD_sections:
981  case OMPD_single:
982  case OMPD_section:
983  case OMPD_master:
984  case OMPD_critical:
985  case OMPD_parallel_for:
986  case OMPD_parallel_for_simd:
987  case OMPD_parallel_sections:
988  case OMPD_task:
989  case OMPD_ordered:
990  case OMPD_atomic:
991  case OMPD_target:
992  case OMPD_teams:
993  case OMPD_taskgroup:
994  case OMPD_target_data:
995  case OMPD_target_parallel:
996  case OMPD_target_parallel_for:
997  case OMPD_taskloop:
998  case OMPD_taskloop_simd:
999  case OMPD_distribute:
1000  case OMPD_distribute_parallel_for:
1001  case OMPD_distribute_parallel_for_simd:
1002  case OMPD_distribute_simd:
1003  case OMPD_target_parallel_for_simd:
1004  case OMPD_target_simd:
1005  case OMPD_teams_distribute:
1006  case OMPD_teams_distribute_simd:
1007  case OMPD_teams_distribute_parallel_for_simd:
1008  case OMPD_teams_distribute_parallel_for:
1009  case OMPD_target_teams:
1010  case OMPD_target_teams_distribute:
1011  case OMPD_target_teams_distribute_parallel_for:
1012  case OMPD_target_teams_distribute_parallel_for_simd:
1013  case OMPD_target_teams_distribute_simd: {
1014  ConsumeToken();
1015  // Parse directive name of the 'critical' directive if any.
1016  if (DKind == OMPD_critical) {
1017  BalancedDelimiterTracker T(*this, tok::l_paren,
1018  tok::annot_pragma_openmp_end);
1019  if (!T.consumeOpen()) {
1020  if (Tok.isAnyIdentifier()) {
1021  DirName =
1022  DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
1023  ConsumeAnyToken();
1024  } else {
1025  Diag(Tok, diag::err_omp_expected_identifier_for_critical);
1026  }
1027  T.consumeClose();
1028  }
1029  } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1030  CancelRegion = ParseOpenMPDirectiveKind(*this);
1031  if (Tok.isNot(tok::annot_pragma_openmp_end))
1032  ConsumeToken();
1033  }
1034 
1035  if (isOpenMPLoopDirective(DKind))
1036  ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
1037  if (isOpenMPSimdDirective(DKind))
1038  ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
1039  ParseScope OMPDirectiveScope(this, ScopeFlags);
1040  Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1041 
1042  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
1043  OpenMPClauseKind CKind =
1044  Tok.isAnnotation()
1045  ? OMPC_unknown
1046  : FlushHasClause ? OMPC_flush
1047  : getOpenMPClauseKind(PP.getSpelling(Tok));
1048  Actions.StartOpenMPClause(CKind);
1049  FlushHasClause = false;
1050  OMPClause *Clause =
1051  ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1052  FirstClauses[CKind].setInt(true);
1053  if (Clause) {
1054  FirstClauses[CKind].setPointer(Clause);
1055  Clauses.push_back(Clause);
1056  }
1057 
1058  // Skip ',' if any.
1059  if (Tok.is(tok::comma))
1060  ConsumeToken();
1061  Actions.EndOpenMPClause();
1062  }
1063  // End location of the directive.
1064  EndLoc = Tok.getLocation();
1065  // Consume final annot_pragma_openmp_end.
1066  ConsumeAnnotationToken();
1067 
1068  // OpenMP [2.13.8, ordered Construct, Syntax]
1069  // If the depend clause is specified, the ordered construct is a stand-alone
1070  // directive.
1071  if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1072  if (Allowed == ACK_StatementsOpenMPNonStandalone) {
1073  Diag(Loc, diag::err_omp_immediate_directive)
1074  << getOpenMPDirectiveName(DKind) << 1
1075  << getOpenMPClauseName(OMPC_depend);
1076  }
1077  HasAssociatedStatement = false;
1078  }
1079 
1080  StmtResult AssociatedStmt;
1081  if (HasAssociatedStatement) {
1082  // The body is a block scope like in Lambdas and Blocks.
1083  Sema::CompoundScopeRAII CompoundScope(Actions);
1084  Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1085  Actions.ActOnStartOfCompoundStmt();
1086  // Parse statement
1087  AssociatedStmt = ParseStatement();
1088  Actions.ActOnFinishOfCompoundStmt();
1089  AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1090  } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1091  DKind == OMPD_target_exit_data) {
1092  Sema::CompoundScopeRAII CompoundScope(Actions);
1093  Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1094  Actions.ActOnStartOfCompoundStmt();
1095  AssociatedStmt =
1096  Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, /*isStmtExpr=*/false);
1097  Actions.ActOnFinishOfCompoundStmt();
1098  AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1099  }
1100  Directive = Actions.ActOnOpenMPExecutableDirective(
1101  DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1102  EndLoc);
1103 
1104  // Exit scope.
1105  Actions.EndOpenMPDSABlock(Directive.get());
1106  OMPDirectiveScope.Exit();
1107  break;
1108  }
1109  case OMPD_declare_simd:
1110  case OMPD_declare_target:
1111  case OMPD_end_declare_target:
1112  Diag(Tok, diag::err_omp_unexpected_directive)
1113  << getOpenMPDirectiveName(DKind);
1114  SkipUntil(tok::annot_pragma_openmp_end);
1115  break;
1116  case OMPD_unknown:
1117  Diag(Tok, diag::err_omp_unknown_directive);
1118  SkipUntil(tok::annot_pragma_openmp_end);
1119  break;
1120  }
1121  return Directive;
1122 }
1123 
1124 // Parses simple list:
1125 // simple-variable-list:
1126 // '(' id-expression {, id-expression} ')'
1127 //
1128 bool Parser::ParseOpenMPSimpleVarList(
1130  const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1131  Callback,
1132  bool AllowScopeSpecifier) {
1133  // Parse '('.
1134  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1135  if (T.expectAndConsume(diag::err_expected_lparen_after,
1137  return true;
1138  bool IsCorrect = true;
1139  bool NoIdentIsFound = true;
1140 
1141  // Read tokens while ')' or annot_pragma_openmp_end is not found.
1142  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1143  CXXScopeSpec SS;
1144  SourceLocation TemplateKWLoc;
1145  UnqualifiedId Name;
1146  // Read var name.
1147  Token PrevTok = Tok;
1148  NoIdentIsFound = false;
1149 
1150  if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1151  ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1152  IsCorrect = false;
1153  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1154  StopBeforeMatch);
1155  } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
1156  TemplateKWLoc, Name)) {
1157  IsCorrect = false;
1158  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1159  StopBeforeMatch);
1160  } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1161  Tok.isNot(tok::annot_pragma_openmp_end)) {
1162  IsCorrect = false;
1163  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1164  StopBeforeMatch);
1165  Diag(PrevTok.getLocation(), diag::err_expected)
1166  << tok::identifier
1167  << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1168  } else {
1169  Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1170  }
1171  // Consume ','.
1172  if (Tok.is(tok::comma)) {
1173  ConsumeToken();
1174  }
1175  }
1176 
1177  if (NoIdentIsFound) {
1178  Diag(Tok, diag::err_expected) << tok::identifier;
1179  IsCorrect = false;
1180  }
1181 
1182  // Parse ')'.
1183  IsCorrect = !T.consumeClose() && IsCorrect;
1184 
1185  return !IsCorrect;
1186 }
1187 
1188 /// \brief Parsing of OpenMP clauses.
1189 ///
1190 /// clause:
1191 /// if-clause | final-clause | num_threads-clause | safelen-clause |
1192 /// default-clause | private-clause | firstprivate-clause | shared-clause
1193 /// | linear-clause | aligned-clause | collapse-clause |
1194 /// lastprivate-clause | reduction-clause | proc_bind-clause |
1195 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1196 /// mergeable-clause | flush-clause | read-clause | write-clause |
1197 /// update-clause | capture-clause | seq_cst-clause | device-clause |
1198 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1199 /// thread_limit-clause | priority-clause | grainsize-clause |
1200 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1201 /// from-clause | is_device_ptr-clause | task_reduction-clause |
1202 /// in_reduction-clause
1203 ///
1204 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1205  OpenMPClauseKind CKind, bool FirstClause) {
1206  OMPClause *Clause = nullptr;
1207  bool ErrorFound = false;
1208  // Check if clause is allowed for the given directive.
1209  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1210  Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1211  << getOpenMPDirectiveName(DKind);
1212  ErrorFound = true;
1213  }
1214 
1215  switch (CKind) {
1216  case OMPC_final:
1217  case OMPC_num_threads:
1218  case OMPC_safelen:
1219  case OMPC_simdlen:
1220  case OMPC_collapse:
1221  case OMPC_ordered:
1222  case OMPC_device:
1223  case OMPC_num_teams:
1224  case OMPC_thread_limit:
1225  case OMPC_priority:
1226  case OMPC_grainsize:
1227  case OMPC_num_tasks:
1228  case OMPC_hint:
1229  // OpenMP [2.5, Restrictions]
1230  // At most one num_threads clause can appear on the directive.
1231  // OpenMP [2.8.1, simd construct, Restrictions]
1232  // Only one safelen clause can appear on a simd directive.
1233  // Only one simdlen clause can appear on a simd directive.
1234  // Only one collapse clause can appear on a simd directive.
1235  // OpenMP [2.9.1, target data construct, Restrictions]
1236  // At most one device clause can appear on the directive.
1237  // OpenMP [2.11.1, task Construct, Restrictions]
1238  // At most one if clause can appear on the directive.
1239  // At most one final clause can appear on the directive.
1240  // OpenMP [teams Construct, Restrictions]
1241  // At most one num_teams clause can appear on the directive.
1242  // At most one thread_limit clause can appear on the directive.
1243  // OpenMP [2.9.1, task Construct, Restrictions]
1244  // At most one priority clause can appear on the directive.
1245  // OpenMP [2.9.2, taskloop Construct, Restrictions]
1246  // At most one grainsize clause can appear on the directive.
1247  // OpenMP [2.9.2, taskloop Construct, Restrictions]
1248  // At most one num_tasks clause can appear on the directive.
1249  if (!FirstClause) {
1250  Diag(Tok, diag::err_omp_more_one_clause)
1251  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1252  ErrorFound = true;
1253  }
1254 
1255  if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1256  Clause = ParseOpenMPClause(CKind);
1257  else
1258  Clause = ParseOpenMPSingleExprClause(CKind);
1259  break;
1260  case OMPC_default:
1261  case OMPC_proc_bind:
1262  // OpenMP [2.14.3.1, Restrictions]
1263  // Only a single default clause may be specified on a parallel, task or
1264  // teams directive.
1265  // OpenMP [2.5, parallel Construct, Restrictions]
1266  // At most one proc_bind clause can appear on the directive.
1267  if (!FirstClause) {
1268  Diag(Tok, diag::err_omp_more_one_clause)
1269  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1270  ErrorFound = true;
1271  }
1272 
1273  Clause = ParseOpenMPSimpleClause(CKind);
1274  break;
1275  case OMPC_schedule:
1276  case OMPC_dist_schedule:
1277  case OMPC_defaultmap:
1278  // OpenMP [2.7.1, Restrictions, p. 3]
1279  // Only one schedule clause can appear on a loop directive.
1280  // OpenMP [2.10.4, Restrictions, p. 106]
1281  // At most one defaultmap clause can appear on the directive.
1282  if (!FirstClause) {
1283  Diag(Tok, diag::err_omp_more_one_clause)
1284  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1285  ErrorFound = true;
1286  }
1287  LLVM_FALLTHROUGH;
1288 
1289  case OMPC_if:
1290  Clause = ParseOpenMPSingleExprWithArgClause(CKind);
1291  break;
1292  case OMPC_nowait:
1293  case OMPC_untied:
1294  case OMPC_mergeable:
1295  case OMPC_read:
1296  case OMPC_write:
1297  case OMPC_update:
1298  case OMPC_capture:
1299  case OMPC_seq_cst:
1300  case OMPC_threads:
1301  case OMPC_simd:
1302  case OMPC_nogroup:
1303  // OpenMP [2.7.1, Restrictions, p. 9]
1304  // Only one ordered clause can appear on a loop directive.
1305  // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1306  // Only one nowait clause can appear on a for directive.
1307  if (!FirstClause) {
1308  Diag(Tok, diag::err_omp_more_one_clause)
1309  << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1310  ErrorFound = true;
1311  }
1312 
1313  Clause = ParseOpenMPClause(CKind);
1314  break;
1315  case OMPC_private:
1316  case OMPC_firstprivate:
1317  case OMPC_lastprivate:
1318  case OMPC_shared:
1319  case OMPC_reduction:
1320  case OMPC_task_reduction:
1321  case OMPC_in_reduction:
1322  case OMPC_linear:
1323  case OMPC_aligned:
1324  case OMPC_copyin:
1325  case OMPC_copyprivate:
1326  case OMPC_flush:
1327  case OMPC_depend:
1328  case OMPC_map:
1329  case OMPC_to:
1330  case OMPC_from:
1331  case OMPC_use_device_ptr:
1332  case OMPC_is_device_ptr:
1333  Clause = ParseOpenMPVarListClause(DKind, CKind);
1334  break;
1335  case OMPC_unknown:
1336  Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1337  << getOpenMPDirectiveName(DKind);
1338  SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1339  break;
1340  case OMPC_threadprivate:
1341  case OMPC_uniform:
1342  Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1343  << getOpenMPDirectiveName(DKind);
1344  SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1345  break;
1346  }
1347  return ErrorFound ? nullptr : Clause;
1348 }
1349 
1350 /// Parses simple expression in parens for single-expression clauses of OpenMP
1351 /// constructs.
1352 /// \param RLoc Returned location of right paren.
1354  SourceLocation &RLoc) {
1355  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1356  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1357  return ExprError();
1358 
1359  SourceLocation ELoc = Tok.getLocation();
1360  ExprResult LHS(ParseCastExpression(
1361  /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1362  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1363  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1364 
1365  // Parse ')'.
1366  T.consumeClose();
1367 
1368  RLoc = T.getCloseLocation();
1369  return Val;
1370 }
1371 
1372 /// \brief Parsing of OpenMP clauses with single expressions like 'final',
1373 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1374 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1375 ///
1376 /// final-clause:
1377 /// 'final' '(' expression ')'
1378 ///
1379 /// num_threads-clause:
1380 /// 'num_threads' '(' expression ')'
1381 ///
1382 /// safelen-clause:
1383 /// 'safelen' '(' expression ')'
1384 ///
1385 /// simdlen-clause:
1386 /// 'simdlen' '(' expression ')'
1387 ///
1388 /// collapse-clause:
1389 /// 'collapse' '(' expression ')'
1390 ///
1391 /// priority-clause:
1392 /// 'priority' '(' expression ')'
1393 ///
1394 /// grainsize-clause:
1395 /// 'grainsize' '(' expression ')'
1396 ///
1397 /// num_tasks-clause:
1398 /// 'num_tasks' '(' expression ')'
1399 ///
1400 /// hint-clause:
1401 /// 'hint' '(' expression ')'
1402 ///
1403 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
1404  SourceLocation Loc = ConsumeToken();
1405  SourceLocation LLoc = Tok.getLocation();
1406  SourceLocation RLoc;
1407 
1408  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1409 
1410  if (Val.isInvalid())
1411  return nullptr;
1412 
1413  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1414 }
1415 
1416 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1417 ///
1418 /// default-clause:
1419 /// 'default' '(' 'none' | 'shared' ')
1420 ///
1421 /// proc_bind-clause:
1422 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
1423 ///
1424 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
1425  SourceLocation Loc = Tok.getLocation();
1426  SourceLocation LOpen = ConsumeToken();
1427  // Parse '('.
1428  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1429  if (T.expectAndConsume(diag::err_expected_lparen_after,
1430  getOpenMPClauseName(Kind)))
1431  return nullptr;
1432 
1433  unsigned Type = getOpenMPSimpleClauseType(
1434  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1435  SourceLocation TypeLoc = Tok.getLocation();
1436  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1437  Tok.isNot(tok::annot_pragma_openmp_end))
1438  ConsumeAnyToken();
1439 
1440  // Parse ')'.
1441  T.consumeClose();
1442 
1443  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
1444  Tok.getLocation());
1445 }
1446 
1447 /// \brief Parsing of OpenMP clauses like 'ordered'.
1448 ///
1449 /// ordered-clause:
1450 /// 'ordered'
1451 ///
1452 /// nowait-clause:
1453 /// 'nowait'
1454 ///
1455 /// untied-clause:
1456 /// 'untied'
1457 ///
1458 /// mergeable-clause:
1459 /// 'mergeable'
1460 ///
1461 /// read-clause:
1462 /// 'read'
1463 ///
1464 /// threads-clause:
1465 /// 'threads'
1466 ///
1467 /// simd-clause:
1468 /// 'simd'
1469 ///
1470 /// nogroup-clause:
1471 /// 'nogroup'
1472 ///
1473 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
1474  SourceLocation Loc = Tok.getLocation();
1475  ConsumeAnyToken();
1476 
1477  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1478 }
1479 
1480 
1481 /// \brief Parsing of OpenMP clauses with single expressions and some additional
1482 /// argument like 'schedule' or 'dist_schedule'.
1483 ///
1484 /// schedule-clause:
1485 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1486 /// ')'
1487 ///
1488 /// if-clause:
1489 /// 'if' '(' [ directive-name-modifier ':' ] expression ')'
1490 ///
1491 /// defaultmap:
1492 /// 'defaultmap' '(' modifier ':' kind ')'
1493 ///
1494 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
1495  SourceLocation Loc = ConsumeToken();
1496  SourceLocation DelimLoc;
1497  // Parse '('.
1498  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1499  if (T.expectAndConsume(diag::err_expected_lparen_after,
1500  getOpenMPClauseName(Kind)))
1501  return nullptr;
1502 
1503  ExprResult Val;
1506  if (Kind == OMPC_schedule) {
1507  enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1508  Arg.resize(NumberOfElements);
1509  KLoc.resize(NumberOfElements);
1510  Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1511  Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1512  Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1513  auto KindModifier = getOpenMPSimpleClauseType(
1514  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1515  if (KindModifier > OMPC_SCHEDULE_unknown) {
1516  // Parse 'modifier'
1517  Arg[Modifier1] = KindModifier;
1518  KLoc[Modifier1] = Tok.getLocation();
1519  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1520  Tok.isNot(tok::annot_pragma_openmp_end))
1521  ConsumeAnyToken();
1522  if (Tok.is(tok::comma)) {
1523  // Parse ',' 'modifier'
1524  ConsumeAnyToken();
1525  KindModifier = getOpenMPSimpleClauseType(
1526  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1527  Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1528  ? KindModifier
1529  : (unsigned)OMPC_SCHEDULE_unknown;
1530  KLoc[Modifier2] = Tok.getLocation();
1531  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1532  Tok.isNot(tok::annot_pragma_openmp_end))
1533  ConsumeAnyToken();
1534  }
1535  // Parse ':'
1536  if (Tok.is(tok::colon))
1537  ConsumeAnyToken();
1538  else
1539  Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1540  KindModifier = getOpenMPSimpleClauseType(
1541  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1542  }
1543  Arg[ScheduleKind] = KindModifier;
1544  KLoc[ScheduleKind] = Tok.getLocation();
1545  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1546  Tok.isNot(tok::annot_pragma_openmp_end))
1547  ConsumeAnyToken();
1548  if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1549  Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1550  Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1551  Tok.is(tok::comma))
1552  DelimLoc = ConsumeAnyToken();
1553  } else if (Kind == OMPC_dist_schedule) {
1554  Arg.push_back(getOpenMPSimpleClauseType(
1555  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1556  KLoc.push_back(Tok.getLocation());
1557  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1558  Tok.isNot(tok::annot_pragma_openmp_end))
1559  ConsumeAnyToken();
1560  if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1561  DelimLoc = ConsumeAnyToken();
1562  } else if (Kind == OMPC_defaultmap) {
1563  // Get a defaultmap modifier
1564  Arg.push_back(getOpenMPSimpleClauseType(
1565  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1566  KLoc.push_back(Tok.getLocation());
1567  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1568  Tok.isNot(tok::annot_pragma_openmp_end))
1569  ConsumeAnyToken();
1570  // Parse ':'
1571  if (Tok.is(tok::colon))
1572  ConsumeAnyToken();
1573  else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1574  Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1575  // Get a defaultmap kind
1576  Arg.push_back(getOpenMPSimpleClauseType(
1577  Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1578  KLoc.push_back(Tok.getLocation());
1579  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1580  Tok.isNot(tok::annot_pragma_openmp_end))
1581  ConsumeAnyToken();
1582  } else {
1583  assert(Kind == OMPC_if);
1584  KLoc.push_back(Tok.getLocation());
1585  TentativeParsingAction TPA(*this);
1586  Arg.push_back(ParseOpenMPDirectiveKind(*this));
1587  if (Arg.back() != OMPD_unknown) {
1588  ConsumeToken();
1589  if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1590  TPA.Commit();
1591  DelimLoc = ConsumeToken();
1592  } else {
1593  TPA.Revert();
1594  Arg.back() = OMPD_unknown;
1595  }
1596  } else
1597  TPA.Revert();
1598  }
1599 
1600  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1601  (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1602  Kind == OMPC_if;
1603  if (NeedAnExpression) {
1604  SourceLocation ELoc = Tok.getLocation();
1605  ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
1606  Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
1607  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1608  }
1609 
1610  // Parse ')'.
1611  T.consumeClose();
1612 
1613  if (NeedAnExpression && Val.isInvalid())
1614  return nullptr;
1615 
1616  return Actions.ActOnOpenMPSingleExprWithArgClause(
1617  Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
1618  T.getCloseLocation());
1619 }
1620 
1621 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
1622  UnqualifiedId &ReductionId) {
1623  SourceLocation TemplateKWLoc;
1624  if (ReductionIdScopeSpec.isEmpty()) {
1625  auto OOK = OO_None;
1626  switch (P.getCurToken().getKind()) {
1627  case tok::plus:
1628  OOK = OO_Plus;
1629  break;
1630  case tok::minus:
1631  OOK = OO_Minus;
1632  break;
1633  case tok::star:
1634  OOK = OO_Star;
1635  break;
1636  case tok::amp:
1637  OOK = OO_Amp;
1638  break;
1639  case tok::pipe:
1640  OOK = OO_Pipe;
1641  break;
1642  case tok::caret:
1643  OOK = OO_Caret;
1644  break;
1645  case tok::ampamp:
1646  OOK = OO_AmpAmp;
1647  break;
1648  case tok::pipepipe:
1649  OOK = OO_PipePipe;
1650  break;
1651  default:
1652  break;
1653  }
1654  if (OOK != OO_None) {
1655  SourceLocation OpLoc = P.ConsumeToken();
1656  SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
1657  ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
1658  return false;
1659  }
1660  }
1661  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
1662  /*AllowDestructorName*/ false,
1663  /*AllowConstructorName*/ false,
1664  /*AllowDeductionGuide*/ false,
1665  nullptr, TemplateKWLoc, ReductionId);
1666 }
1667 
1668 /// Parses clauses with list.
1672  OpenMPVarListDataTy &Data) {
1673  UnqualifiedId UnqualifiedReductionId;
1674  bool InvalidReductionId = false;
1675  bool MapTypeModifierSpecified = false;
1676 
1677  // Parse '('.
1678  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1679  if (T.expectAndConsume(diag::err_expected_lparen_after,
1680  getOpenMPClauseName(Kind)))
1681  return true;
1682 
1683  bool NeedRParenForLinear = false;
1684  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
1685  tok::annot_pragma_openmp_end);
1686  // Handle reduction-identifier for reduction clause.
1687  if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
1688  Kind == OMPC_in_reduction) {
1689  ColonProtectionRAIIObject ColonRAII(*this);
1690  if (getLangOpts().CPlusPlus)
1691  ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
1692  /*ObjectType=*/nullptr,
1693  /*EnteringContext=*/false);
1694  InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec,
1695  UnqualifiedReductionId);
1696  if (InvalidReductionId) {
1697  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1698  StopBeforeMatch);
1699  }
1700  if (Tok.is(tok::colon))
1701  Data.ColonLoc = ConsumeToken();
1702  else
1703  Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
1704  if (!InvalidReductionId)
1705  Data.ReductionId =
1706  Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
1707  } else if (Kind == OMPC_depend) {
1708  // Handle dependency type for depend clause.
1709  ColonProtectionRAIIObject ColonRAII(*this);
1710  Data.DepKind =
1712  Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
1713  Data.DepLinMapLoc = Tok.getLocation();
1714 
1715  if (Data.DepKind == OMPC_DEPEND_unknown) {
1716  SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1717  StopBeforeMatch);
1718  } else {
1719  ConsumeToken();
1720  // Special processing for depend(source) clause.
1721  if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
1722  // Parse ')'.
1723  T.consumeClose();
1724  return false;
1725  }
1726  }
1727  if (Tok.is(tok::colon))
1728  Data.ColonLoc = ConsumeToken();
1729  else {
1730  Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
1731  : diag::warn_pragma_expected_colon)
1732  << "dependency type";
1733  }
1734  } else if (Kind == OMPC_linear) {
1735  // Try to parse modifier if any.
1736  if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
1737  Data.LinKind = static_cast<OpenMPLinearClauseKind>(
1738  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
1739  Data.DepLinMapLoc = ConsumeToken();
1740  LinearT.consumeOpen();
1741  NeedRParenForLinear = true;
1742  }
1743  } else if (Kind == OMPC_map) {
1744  // Handle map type for map clause.
1745  ColonProtectionRAIIObject ColonRAII(*this);
1746 
1747  /// The map clause modifier token can be either a identifier or the C++
1748  /// delete keyword.
1749  auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
1750  return Tok.isOneOf(tok::identifier, tok::kw_delete);
1751  };
1752 
1753  // The first identifier may be a list item, a map-type or a
1754  // map-type-modifier. The map modifier can also be delete which has the same
1755  // spelling of the C++ delete keyword.
1756  Data.MapType =
1757  IsMapClauseModifierToken(Tok)
1758  ? static_cast<OpenMPMapClauseKind>(
1759  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1760  : OMPC_MAP_unknown;
1761  Data.DepLinMapLoc = Tok.getLocation();
1762  bool ColonExpected = false;
1763 
1764  if (IsMapClauseModifierToken(Tok)) {
1765  if (PP.LookAhead(0).is(tok::colon)) {
1766  if (Data.MapType == OMPC_MAP_unknown)
1767  Diag(Tok, diag::err_omp_unknown_map_type);
1768  else if (Data.MapType == OMPC_MAP_always)
1769  Diag(Tok, diag::err_omp_map_type_missing);
1770  ConsumeToken();
1771  } else if (PP.LookAhead(0).is(tok::comma)) {
1772  if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
1773  PP.LookAhead(2).is(tok::colon)) {
1774  Data.MapTypeModifier = Data.MapType;
1775  if (Data.MapTypeModifier != OMPC_MAP_always) {
1776  Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1778  } else
1779  MapTypeModifierSpecified = true;
1780 
1781  ConsumeToken();
1782  ConsumeToken();
1783 
1784  Data.MapType =
1785  IsMapClauseModifierToken(Tok)
1786  ? static_cast<OpenMPMapClauseKind>(
1787  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1788  : OMPC_MAP_unknown;
1789  if (Data.MapType == OMPC_MAP_unknown ||
1790  Data.MapType == OMPC_MAP_always)
1791  Diag(Tok, diag::err_omp_unknown_map_type);
1792  ConsumeToken();
1793  } else {
1794  Data.MapType = OMPC_MAP_tofrom;
1795  Data.IsMapTypeImplicit = true;
1796  }
1797  } else if (IsMapClauseModifierToken(PP.LookAhead(0))) {
1798  if (PP.LookAhead(1).is(tok::colon)) {
1799  Data.MapTypeModifier = Data.MapType;
1800  if (Data.MapTypeModifier != OMPC_MAP_always) {
1801  Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1803  } else
1804  MapTypeModifierSpecified = true;
1805 
1806  ConsumeToken();
1807 
1808  Data.MapType =
1809  IsMapClauseModifierToken(Tok)
1810  ? static_cast<OpenMPMapClauseKind>(
1811  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1812  : OMPC_MAP_unknown;
1813  if (Data.MapType == OMPC_MAP_unknown ||
1814  Data.MapType == OMPC_MAP_always)
1815  Diag(Tok, diag::err_omp_unknown_map_type);
1816  ConsumeToken();
1817  } else {
1818  Data.MapType = OMPC_MAP_tofrom;
1819  Data.IsMapTypeImplicit = true;
1820  }
1821  } else {
1822  Data.MapType = OMPC_MAP_tofrom;
1823  Data.IsMapTypeImplicit = true;
1824  }
1825  } else {
1826  Data.MapType = OMPC_MAP_tofrom;
1827  Data.IsMapTypeImplicit = true;
1828  }
1829 
1830  if (Tok.is(tok::colon))
1831  Data.ColonLoc = ConsumeToken();
1832  else if (ColonExpected)
1833  Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
1834  }
1835 
1836  bool IsComma =
1837  (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
1838  Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
1839  (Kind == OMPC_reduction && !InvalidReductionId) ||
1840  (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
1841  (!MapTypeModifierSpecified ||
1842  Data.MapTypeModifier == OMPC_MAP_always)) ||
1843  (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
1844  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
1845  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
1846  Tok.isNot(tok::annot_pragma_openmp_end))) {
1847  ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
1848  // Parse variable
1849  ExprResult VarExpr =
1850  Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
1851  if (VarExpr.isUsable())
1852  Vars.push_back(VarExpr.get());
1853  else {
1854  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1855  StopBeforeMatch);
1856  }
1857  // Skip ',' if any
1858  IsComma = Tok.is(tok::comma);
1859  if (IsComma)
1860  ConsumeToken();
1861  else if (Tok.isNot(tok::r_paren) &&
1862  Tok.isNot(tok::annot_pragma_openmp_end) &&
1863  (!MayHaveTail || Tok.isNot(tok::colon)))
1864  Diag(Tok, diag::err_omp_expected_punc)
1865  << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
1866  : getOpenMPClauseName(Kind))
1867  << (Kind == OMPC_flush);
1868  }
1869 
1870  // Parse ')' for linear clause with modifier.
1871  if (NeedRParenForLinear)
1872  LinearT.consumeClose();
1873 
1874  // Parse ':' linear-step (or ':' alignment).
1875  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
1876  if (MustHaveTail) {
1877  Data.ColonLoc = Tok.getLocation();
1878  SourceLocation ELoc = ConsumeToken();
1879  ExprResult Tail = ParseAssignmentExpression();
1880  Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
1881  if (Tail.isUsable())
1882  Data.TailExpr = Tail.get();
1883  else
1884  SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1885  StopBeforeMatch);
1886  }
1887 
1888  // Parse ')'.
1889  T.consumeClose();
1890  if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
1891  Vars.empty()) ||
1892  (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
1893  (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
1894  return true;
1895  return false;
1896 }
1897 
1898 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
1899 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
1900 /// 'in_reduction'.
1901 ///
1902 /// private-clause:
1903 /// 'private' '(' list ')'
1904 /// firstprivate-clause:
1905 /// 'firstprivate' '(' list ')'
1906 /// lastprivate-clause:
1907 /// 'lastprivate' '(' list ')'
1908 /// shared-clause:
1909 /// 'shared' '(' list ')'
1910 /// linear-clause:
1911 /// 'linear' '(' linear-list [ ':' linear-step ] ')'
1912 /// aligned-clause:
1913 /// 'aligned' '(' list [ ':' alignment ] ')'
1914 /// reduction-clause:
1915 /// 'reduction' '(' reduction-identifier ':' list ')'
1916 /// task_reduction-clause:
1917 /// 'task_reduction' '(' reduction-identifier ':' list ')'
1918 /// in_reduction-clause:
1919 /// 'in_reduction' '(' reduction-identifier ':' list ')'
1920 /// copyprivate-clause:
1921 /// 'copyprivate' '(' list ')'
1922 /// flush-clause:
1923 /// 'flush' '(' list ')'
1924 /// depend-clause:
1925 /// 'depend' '(' in | out | inout : list | source ')'
1926 /// map-clause:
1927 /// 'map' '(' [ [ always , ]
1928 /// to | from | tofrom | alloc | release | delete ':' ] list ')';
1929 /// to-clause:
1930 /// 'to' '(' list ')'
1931 /// from-clause:
1932 /// 'from' '(' list ')'
1933 /// use_device_ptr-clause:
1934 /// 'use_device_ptr' '(' list ')'
1935 /// is_device_ptr-clause:
1936 /// 'is_device_ptr' '(' list ')'
1937 ///
1938 /// For 'linear' clause linear-list may have the following forms:
1939 /// list
1940 /// modifier(list)
1941 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
1942 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
1944  SourceLocation Loc = Tok.getLocation();
1945  SourceLocation LOpen = ConsumeToken();
1947  OpenMPVarListDataTy Data;
1948 
1949  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
1950  return nullptr;
1951 
1952  return Actions.ActOnOpenMPVarListClause(
1953  Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
1954  Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
1955  Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
1956  Data.DepLinMapLoc);
1957 }
1958 
OpenMPDependClauseKind DepKind
Definition: Parser.h:2712
Defines the clang::ASTContext interface.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Called on correct id-expression from the &#39;#pragma omp threadprivate&#39;.
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.
PtrTy get() const
Definition: Ownership.h:74
ParseScope - Introduces a new scope for parsing.
Definition: Parser.h:851
DeclarationNameInfo ReductionId
Definition: Parser.h:2711
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
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:95
bool isEmpty() const
No scope specifier.
Definition: DeclSpec.h:189
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
StringRef P
The base class of the type hierarchy.
Definition: Type.h:1351
SourceLocation getCloseLocation() const
This indicates that the scope corresponds to a function, which means that labels are set here...
Definition: Scope.h:46
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind)
static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P)
Definition: ParseOpenMP.cpp:83
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:95
void ActOnExitFunctionContext()
Definition: SemaDecl.cpp:1313
Wrapper for void* pointer.
Definition: Ownership.h:45
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:57
bool isEmpty() const
Evaluates true when this declaration name is empty.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:806
TypeSpecifierType
Specifies the kind of type.
Definition: Specifiers.h:45
RAII object used to temporarily allow the C++ &#39;this&#39; expression to be used, with the given qualifiers...
Definition: Sema.h:5040
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing...
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed...
tok::TokenKind getKind() const
Definition: Token.h:90
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
Definition: Parser.h:945
OpenMPLinearClauseKind LinKind
Definition: Parser.h:2713
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:56
RecordDecl - Represents a struct/union/class.
Definition: Decl.h:3488
const char * getOpenMPClauseName(OpenMPClauseKind Kind)
Definition: OpenMPKinds.cpp:62
One of these records is kept for each identifier that is lexed.
OpenMPLinearClauseKind
OpenMP attributes for &#39;linear&#39; clause.
Definition: OpenMPKinds.h:84
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, ParsedType ObjectType, SourceLocation &TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
VerifyDiagnosticConsumer::Directive Directive
Represents a C++ unqualified-id that has been parsed.
Definition: DeclSpec.h:910
PtrTy get() const
Definition: Ownership.h:162
bool isNot(T Kind) const
Definition: FormatToken.h:313
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the &#39;spelling&#39; of the token at the given location; does not go up to the spelling location or ...
const FormatToken & Tok
StmtResult StmtError()
Definition: Ownership.h:268
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str)
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 &#39;declare simd&#39; directive.
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:63
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:274
bool isOneOf(A K1, B K2) const
Definition: FormatToken.h:306
A RAII object to enter scope of a compound statement.
Definition: Sema.h:3673
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:540
OpenMPMapClauseKind MapTypeModifier
Definition: Parser.h:2714
const FunctionProtoType * T
This is the scope of OpenMP executable directive.
Definition: Scope.h:106
Sema & getActions() const
Definition: Parser.h:274
const Token & getCurToken() const
Definition: Parser.h:277
OpenMPDirectiveKindEx
Definition: ParseOpenMP.cpp:29
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:124
OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:33
DeclContext * getDeclContext()
Definition: DeclBase.h:425
This is a compound statement scope.
Definition: Scope.h:129
Preprocessor & getPreprocessor() const
Definition: Parser.h:273
bool isInvalid() const
Definition: Ownership.h:158
SourceLocation getOpenLocation() const
bool isUsable() const
Definition: Ownership.h:159
A class for parsing a DeclSpec.
bool isTemplateDecl() const
returns true if this declaration is a template
Definition: DeclBase.cpp:228
Kind
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Definition: Ownership.h:144
ASTContext & getASTContext() const
Definition: Sema.h:1200
Encodes a location in the source.
OpenMPDependClauseKind
OpenMP attributes for &#39;depend&#39; clause.
Definition: OpenMPKinds.h:76
bool is(tok::TokenKind Kind) const
Definition: FormatToken.h:297
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr *> &Vars, OpenMPVarListDataTy &Data)
Parses clauses with list.
static unsigned getOpenMPDirectiveKindEx(StringRef S)
Definition: ParseOpenMP.cpp:65
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:177
OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:23
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:51
Scope * getCurScope() const
Definition: Parser.h:278
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
StringRef getName() const
Return the actual identifier string.
bool isNot(tok::TokenKind K) const
Definition: Token.h:96
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
Definition: Parser.cpp:2243
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:22
This is the scope of some OpenMP simd directive.
Definition: Scope.h:114
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
Definition: DeclBase.h:1010
This is a scope that corresponds to the template parameters of a C++ template.
Definition: Scope.h:76
DeclarationName - The name of a declaration.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
Data used for parsing list of variables in OpenMP clauses.
Definition: Parser.h:2707
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
static const TST TST_unspecified
Definition: DeclSpec.h:272
Not an overloaded operator.
Definition: OperatorKinds.h:23
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
QualType getCanonicalTypeInternal() const
Definition: Type.h:2107
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Definition: Parser.cpp:72
This file defines OpenMP AST classes for executable directives and clauses.
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
Definition: DeclSpec.cpp:1281
ActionResult< Stmt * > StmtResult
Definition: Ownership.h:252
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str)
const char * getOpenMPDirectiveName(OpenMPDirectiveKind Kind)
Definition: OpenMPKinds.cpp:31
This is a scope that can contain a declaration.
Definition: Scope.h:58
SourceLocation ConsumeToken()
ConsumeToken - Consume the current &#39;peek token&#39; and lex the next one.
Definition: Parser.h:316
OpenMPMapClauseKind
OpenMP mapping kind for &#39;map&#39; clause.
Definition: OpenMPKinds.h:92
static DeclarationName parseOpenMPReductionId(Parser &P)
This is the scope of some OpenMP loop directive.
Definition: Scope.h:109
ExprResult ExprError()
Definition: Ownership.h:267
QualType getType() const
Definition: Decl.h:638
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
A trivial tuple used to represent a source range.
NamedDecl - This represents a decl with a name.
Definition: Decl.h:245
Directive - Abstract class representing a parsed verify directive.
SourceLocation getBegin() const
SourceLocation getLocation() const
Definition: DeclBase.h:416
OpenMPMapClauseKind MapType
Definition: Parser.h:2715
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition: Decl.cpp:1689
Stop skipping at specified token, but don&#39;t skip the token itself.
Definition: Parser.h:927
SourceLocation getEndLoc() const
Definition: Token.h:151