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