ParseOpenMP.cpp revision 314564
1193323Sed//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed/// \file
10193323Sed/// \brief This file implements parsing of all OpenMP directives and clauses.
11193323Sed///
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#include "RAIIObjectsForParser.h"
15193323Sed#include "clang/AST/ASTContext.h"
16193323Sed#include "clang/AST/StmtOpenMP.h"
17193323Sed#include "clang/Parse/ParseDiagnostic.h"
18193323Sed#include "clang/Parse/Parser.h"
19249423Sdim#include "clang/Sema/Scope.h"
20249423Sdim#include "llvm/ADT/PointerIntPair.h"
21193323Sed
22193323Sedusing namespace clang;
23198892Srdivacky
24218893Sdim//===----------------------------------------------------------------------===//
25249423Sdim// OpenMP declarative directives.
26249423Sdim//===----------------------------------------------------------------------===//
27249423Sdim
28249423Sdimnamespace {
29249423Sdimenum OpenMPDirectiveKindEx {
30249423Sdim  OMPD_cancellation = OMPD_unknown + 1,
31193323Sed  OMPD_data,
32193323Sed  OMPD_declare,
33193323Sed  OMPD_end,
34193323Sed  OMPD_end_declare,
35193323Sed  OMPD_enter,
36193323Sed  OMPD_exit,
37193323Sed  OMPD_point,
38193323Sed  OMPD_reduction,
39193323Sed  OMPD_target_enter,
40193323Sed  OMPD_target_exit,
41193323Sed  OMPD_update,
42193323Sed  OMPD_distribute_parallel,
43193323Sed  OMPD_teams_distribute_parallel,
44193323Sed  OMPD_target_teams_distribute_parallel
45193323Sed};
46193323Sed
47193323Sedclass ThreadprivateListParserHelper final {
48198892Srdivacky  SmallVector<Expr *, 4> Identifiers;
49193323Sed  Parser *P;
50193323Sed
51193323Sedpublic:
52212904Sdim  ThreadprivateListParserHelper(Parser *P) : P(P) {}
53193323Sed  void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
54193323Sed    ExprResult Res =
55193323Sed        P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo);
56193323Sed    if (Res.isUsable())
57212904Sdim      Identifiers.push_back(Res.get());
58193323Sed  }
59212904Sdim  llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
60212904Sdim};
61193323Sed} // namespace
62193323Sed
63193323Sed// Map token string to extended OMP token kind that are
64193323Sed// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
65193323Sedstatic unsigned getOpenMPDirectiveKindEx(StringRef S) {
66193323Sed  auto DKind = getOpenMPDirectiveKind(S);
67193323Sed  if (DKind != OMPD_unknown)
68193323Sed    return DKind;
69193323Sed
70193323Sed  return llvm::StringSwitch<unsigned>(S)
71193323Sed      .Case("cancellation", OMPD_cancellation)
72193323Sed      .Case("data", OMPD_data)
73193323Sed      .Case("declare", OMPD_declare)
74198892Srdivacky      .Case("end", OMPD_end)
75193323Sed      .Case("enter", OMPD_enter)
76193323Sed      .Case("exit", OMPD_exit)
77212904Sdim      .Case("point", OMPD_point)
78193323Sed      .Case("reduction", OMPD_reduction)
79193323Sed      .Case("update", OMPD_update)
80193323Sed      .Default(OMPD_unknown);
81212904Sdim}
82193323Sed
83193323Sedstatic OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
84193323Sed  // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
85212904Sdim  // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
86193323Sed  // TODO: add other combined directives in topological order.
87193323Sed  static const unsigned F[][3] = {
88193323Sed    { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
89212904Sdim    { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
90193323Sed    { OMPD_declare, OMPD_simd, OMPD_declare_simd },
91193323Sed    { OMPD_declare, OMPD_target, OMPD_declare_target },
92193323Sed    { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
93218893Sdim    { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
94218893Sdim    { OMPD_distribute_parallel_for, OMPD_simd,
95218893Sdim      OMPD_distribute_parallel_for_simd },
96193323Sed    { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
97193323Sed    { OMPD_end, OMPD_declare, OMPD_end_declare },
98193323Sed    { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
99193323Sed    { OMPD_target, OMPD_data, OMPD_target_data },
100193323Sed    { OMPD_target, OMPD_enter, OMPD_target_enter },
101193323Sed    { OMPD_target, OMPD_exit, OMPD_target_exit },
102193323Sed    { OMPD_target, OMPD_update, OMPD_target_update },
103193323Sed    { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
104193323Sed    { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
105193323Sed    { OMPD_for, OMPD_simd, OMPD_for_simd },
106193323Sed    { OMPD_parallel, OMPD_for, OMPD_parallel_for },
107193323Sed    { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
108193323Sed    { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
109193323Sed    { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
110193323Sed    { OMPD_target, OMPD_parallel, OMPD_target_parallel },
111193323Sed    { OMPD_target, OMPD_simd, OMPD_target_simd },
112193323Sed    { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
113218893Sdim    { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd },
114212904Sdim    { OMPD_teams, OMPD_distribute, OMPD_teams_distribute },
115218893Sdim    { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd },
116212904Sdim    { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel },
117212904Sdim    { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for },
118212904Sdim    { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd },
119193323Sed    { OMPD_target, OMPD_teams, OMPD_target_teams },
120193323Sed    { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute },
121193323Sed    { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel },
122193323Sed    { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
123193323Sed    { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
124212904Sdim    { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
125218893Sdim  };
126218893Sdim  enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
127193323Sed  auto Tok = P.getCurToken();
128193323Sed  unsigned DKind =
129218893Sdim      Tok.isAnnotation()
130193323Sed          ? static_cast<unsigned>(OMPD_unknown)
131218893Sdim          : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
132193323Sed  if (DKind == OMPD_unknown)
133218893Sdim    return OMPD_unknown;
134218893Sdim
135193323Sed  for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
136193323Sed    if (DKind != F[i][0])
137193323Sed      continue;
138193323Sed
139193323Sed    Tok = P.getPreprocessor().LookAhead(0);
140212904Sdim    unsigned SDKind =
141218893Sdim        Tok.isAnnotation()
142218893Sdim            ? static_cast<unsigned>(OMPD_unknown)
143218893Sdim            : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
144218893Sdim    if (SDKind == OMPD_unknown)
145218893Sdim      continue;
146218893Sdim
147218893Sdim    if (SDKind == F[i][1]) {
148218893Sdim      P.ConsumeToken();
149218893Sdim      DKind = F[i][2];
150218893Sdim    }
151218893Sdim  }
152193323Sed  return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
153193323Sed                              : OMPD_unknown;
154193323Sed}
155193323Sed
156218893Sdimstatic DeclarationName parseOpenMPReductionId(Parser &P) {
157193323Sed  Token Tok = P.getCurToken();
158202878Srdivacky  Sema &Actions = P.getActions();
159202878Srdivacky  OverloadedOperatorKind OOK = OO_None;
160202878Srdivacky  // Allow to use 'operator' keyword for C++ operators
161202878Srdivacky  bool WithOperator = false;
162212904Sdim  if (Tok.is(tok::kw_operator)) {
163212904Sdim    P.ConsumeToken();
164202878Srdivacky    Tok = P.getCurToken();
165202878Srdivacky    WithOperator = true;
166202878Srdivacky  }
167202878Srdivacky  switch (Tok.getKind()) {
168193323Sed  case tok::plus: // '+'
169193323Sed    OOK = OO_Plus;
170193323Sed    break;
171212904Sdim  case tok::minus: // '-'
172212904Sdim    OOK = OO_Minus;
173212904Sdim    break;
174193323Sed  case tok::star: // '*'
175193323Sed    OOK = OO_Star;
176193323Sed    break;
177193323Sed  case tok::amp: // '&'
178193323Sed    OOK = OO_Amp;
179193323Sed    break;
180193323Sed  case tok::pipe: // '|'
181193323Sed    OOK = OO_Pipe;
182193323Sed    break;
183193323Sed  case tok::caret: // '^'
184193323Sed    OOK = OO_Caret;
185193323Sed    break;
186193323Sed  case tok::ampamp: // '&&'
187193323Sed    OOK = OO_AmpAmp;
188193323Sed    break;
189218893Sdim  case tok::pipepipe: // '||'
190212904Sdim    OOK = OO_PipePipe;
191218893Sdim    break;
192263508Sdim  case tok::identifier: // identifier
193218893Sdim    if (!WithOperator)
194218893Sdim      break;
195218893Sdim  default:
196193323Sed    P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
197193323Sed    P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
198193323Sed                Parser::StopBeforeMatch);
199193323Sed    return DeclarationName();
200193323Sed  }
201193323Sed  P.ConsumeToken();
202193323Sed  auto &DeclNames = Actions.getASTContext().DeclarationNames;
203193323Sed  return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
204193323Sed                        : DeclNames.getCXXOperatorName(OOK);
205193323Sed}
206193323Sed
207193323Sed/// \brief Parse 'omp declare reduction' construct.
208193323Sed///
209193323Sed///       declare-reduction-directive:
210193323Sed///        annot_pragma_openmp 'declare' 'reduction'
211193323Sed///        '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
212193323Sed///        ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
213193323Sed///        annot_pragma_openmp_end
214193323Sed/// <reduction_id> is either a base language identifier or one of the following
215193323Sed/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
216193323Sed///
217193323SedParser::DeclGroupPtrTy
218193323SedParser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
219193323Sed  // Parse '('.
220193323Sed  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
221193323Sed  if (T.expectAndConsume(diag::err_expected_lparen_after,
222193323Sed                         getOpenMPDirectiveName(OMPD_declare_reduction))) {
223193323Sed    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
224193323Sed    return DeclGroupPtrTy();
225193323Sed  }
226193323Sed
227193323Sed  DeclarationName Name = parseOpenMPReductionId(*this);
228193323Sed  if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
229193323Sed    return DeclGroupPtrTy();
230193323Sed
231204642Srdivacky  // Consume ':'.
232193323Sed  bool IsCorrect = !ExpectAndConsume(tok::colon);
233193323Sed
234193323Sed  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
235193323Sed    return DeclGroupPtrTy();
236193323Sed
237193323Sed  IsCorrect = IsCorrect && !Name.isEmpty();
238193323Sed
239193323Sed  if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
240193323Sed    Diag(Tok.getLocation(), diag::err_expected_type);
241193323Sed    IsCorrect = false;
242193323Sed  }
243193323Sed
244193323Sed  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
245193323Sed    return DeclGroupPtrTy();
246193323Sed
247193323Sed  SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
248193323Sed  // Parse list of types until ':' token.
249204642Srdivacky  do {
250193323Sed    ColonProtectionRAIIObject ColonRAII(*this);
251210299Sed    SourceRange Range;
252210299Sed    TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS);
253210299Sed    if (TR.isUsable()) {
254193323Sed      auto ReductionType =
255210299Sed          Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
256193323Sed      if (!ReductionType.isNull()) {
257193323Sed        ReductionTypes.push_back(
258193323Sed            std::make_pair(ReductionType, Range.getBegin()));
259193323Sed      }
260193323Sed    } else {
261210299Sed      SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
262193323Sed                StopBeforeMatch);
263210299Sed    }
264198090Srdivacky
265198090Srdivacky    if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
266243830Sdim      break;
267210299Sed
268210299Sed    // Consume ','.
269193323Sed    if (ExpectAndConsume(tok::comma)) {
270193323Sed      IsCorrect = false;
271210299Sed      if (Tok.is(tok::annot_pragma_openmp_end)) {
272210299Sed        Diag(Tok.getLocation(), diag::err_expected_type);
273210299Sed        return DeclGroupPtrTy();
274193323Sed      }
275193323Sed    }
276210299Sed  } while (Tok.isNot(tok::annot_pragma_openmp_end));
277210299Sed
278210299Sed  if (ReductionTypes.empty()) {
279193323Sed    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
280193323Sed    return DeclGroupPtrTy();
281193323Sed  }
282193323Sed
283193323Sed  if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
284193323Sed    return DeclGroupPtrTy();
285193323Sed
286210299Sed  // Consume ':'.
287193323Sed  if (ExpectAndConsume(tok::colon))
288193323Sed    IsCorrect = false;
289193323Sed
290193323Sed  if (Tok.is(tok::annot_pragma_openmp_end)) {
291193323Sed    Diag(Tok.getLocation(), diag::err_expected_expression);
292210299Sed    return DeclGroupPtrTy();
293210299Sed  }
294193323Sed
295193323Sed  DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
296193323Sed      getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
297193323Sed
298193323Sed  // Parse <combiner> expression and then parse initializer if any for each
299193323Sed  // correct type.
300193323Sed  unsigned I = 0, E = ReductionTypes.size();
301193323Sed  for (auto *D : DRD.get()) {
302193323Sed    TentativeParsingAction TPA(*this);
303193323Sed    ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
304193323Sed                                    Scope::OpenMPDirectiveScope);
305193323Sed    // Parse <combiner> expression.
306193323Sed    Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
307193323Sed    ExprResult CombinerResult =
308193323Sed        Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
309193323Sed                                    D->getLocation(), /*DiscardedValue=*/true);
310193323Sed    Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
311193323Sed
312210299Sed    if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
313210299Sed        Tok.isNot(tok::annot_pragma_openmp_end)) {
314193323Sed      TPA.Commit();
315193323Sed      IsCorrect = false;
316193323Sed      break;
317193323Sed    }
318193323Sed    IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
319193323Sed    ExprResult InitializerResult;
320193323Sed    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
321210299Sed      // Parse <initializer> expression.
322193323Sed      if (Tok.is(tok::identifier) &&
323193323Sed          Tok.getIdentifierInfo()->isStr("initializer"))
324193323Sed        ConsumeToken();
325193323Sed      else {
326193323Sed        Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
327193323Sed        TPA.Commit();
328193323Sed        IsCorrect = false;
329193323Sed        break;
330218893Sdim      }
331193323Sed      // Parse '('.
332243830Sdim      BalancedDelimiterTracker T(*this, tok::l_paren,
333193323Sed                                 tok::annot_pragma_openmp_end);
334193323Sed      IsCorrect =
335193323Sed          !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
336193323Sed          IsCorrect;
337193323Sed      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
338193323Sed        ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
339193323Sed                                        Scope::OpenMPDirectiveScope);
340193323Sed        // Parse expression.
341193323Sed        Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), D);
342193323Sed        InitializerResult = Actions.ActOnFinishFullExpr(
343193323Sed            ParseAssignmentExpression().get(), D->getLocation(),
344193323Sed            /*DiscardedValue=*/true);
345193323Sed        Actions.ActOnOpenMPDeclareReductionInitializerEnd(
346193323Sed            D, InitializerResult.get());
347193323Sed        if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
348193323Sed            Tok.isNot(tok::annot_pragma_openmp_end)) {
349193323Sed          TPA.Commit();
350193323Sed          IsCorrect = false;
351193323Sed          break;
352193323Sed        }
353193323Sed        IsCorrect =
354193323Sed            !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
355193323Sed      }
356193323Sed    }
357193323Sed
358193323Sed    ++I;
359193323Sed    // Revert parsing if not the last type, otherwise accept it, we're done with
360193323Sed    // parsing.
361193323Sed    if (I != E)
362193323Sed      TPA.Revert();
363193323Sed    else
364193323Sed      TPA.Commit();
365193323Sed  }
366193323Sed  return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
367193323Sed                                                         IsCorrect);
368193323Sed}
369193323Sed
370193323Sednamespace {
371193323Sed/// RAII that recreates function context for correct parsing of clauses of
372193323Sed/// 'declare simd' construct.
373193323Sed/// OpenMP, 2.8.2 declare simd Construct
374193323Sed/// The expressions appearing in the clauses of this directive are evaluated in
375193323Sed/// the scope of the arguments of the function declaration or definition.
376193323Sedclass FNContextRAII final {
377193323Sed  Parser &P;
378193323Sed  Sema::CXXThisScopeRAII *ThisScope;
379193323Sed  Parser::ParseScope *TempScope;
380193323Sed  Parser::ParseScope *FnScope;
381193323Sed  bool HasTemplateScope = false;
382193323Sed  bool HasFunScope = false;
383193323Sed  FNContextRAII() = delete;
384193323Sed  FNContextRAII(const FNContextRAII &) = delete;
385193323Sed  FNContextRAII &operator=(const FNContextRAII &) = delete;
386193323Sed
387193323Sedpublic:
388193323Sed  FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
389193323Sed    Decl *D = *Ptr.get().begin();
390193323Sed    NamedDecl *ND = dyn_cast<NamedDecl>(D);
391193323Sed    RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
392193323Sed    Sema &Actions = P.getActions();
393193323Sed
394193323Sed    // Allow 'this' within late-parsed attributes.
395193323Sed    ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, /*TypeQuals=*/0,
396193323Sed                                           ND && ND->isCXXInstanceMember());
397193323Sed
398193323Sed    // If the Decl is templatized, add template parameters to scope.
399193323Sed    HasTemplateScope = D->isTemplateDecl();
400193323Sed    TempScope =
401193323Sed        new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
402193323Sed    if (HasTemplateScope)
403193323Sed      Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
404193323Sed
405193323Sed    // If the Decl is on a function, add function parameters to the scope.
406193323Sed    HasFunScope = D->isFunctionOrFunctionTemplate();
407193323Sed    FnScope = new Parser::ParseScope(&P, Scope::FnScope | Scope::DeclScope,
408193323Sed                                     HasFunScope);
409193323Sed    if (HasFunScope)
410193323Sed      Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
411193323Sed  }
412193323Sed  ~FNContextRAII() {
413193323Sed    if (HasFunScope) {
414193323Sed      P.getActions().ActOnExitFunctionContext();
415193323Sed      FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
416193323Sed    }
417193323Sed    if (HasTemplateScope)
418193323Sed      TempScope->Exit();
419193323Sed    delete FnScope;
420212904Sdim    delete TempScope;
421193323Sed    delete ThisScope;
422193323Sed  }
423193323Sed};
424193323Sed} // namespace
425193323Sed
426193323Sed/// Parses clauses for 'declare simd' directive.
427193323Sed///    clause:
428193323Sed///      'inbranch' | 'notinbranch'
429193323Sed///      'simdlen' '(' <expr> ')'
430193323Sed///      { 'uniform' '(' <argument_list> ')' }
431193323Sed///      { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
432193323Sed///      { 'linear '(' <argument_list> [ ':' <step> ] ')' }
433193323Sedstatic bool parseDeclareSimdClauses(
434193323Sed    Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
435193323Sed    SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
436193323Sed    SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
437193323Sed    SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
438193323Sed  SourceRange BSRange;
439193323Sed  const Token &Tok = P.getCurToken();
440193323Sed  bool IsError = false;
441193323Sed  while (Tok.isNot(tok::annot_pragma_openmp_end)) {
442193323Sed    if (Tok.isNot(tok::identifier))
443193323Sed      break;
444193323Sed    OMPDeclareSimdDeclAttr::BranchStateTy Out;
445193323Sed    IdentifierInfo *II = Tok.getIdentifierInfo();
446193323Sed    StringRef ClauseName = II->getName();
447193323Sed    // Parse 'inranch|notinbranch' clauses.
448193323Sed    if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
449193323Sed      if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
450239462Sdim        P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
451193323Sed            << ClauseName
452239462Sdim            << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
453193323Sed        IsError = true;
454193323Sed      }
455193323Sed      BS = Out;
456239462Sdim      BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
457193323Sed      P.ConsumeToken();
458239462Sdim    } else if (ClauseName.equals("simdlen")) {
459193323Sed      if (SimdLen.isUsable()) {
460193323Sed        P.Diag(Tok, diag::err_omp_more_one_clause)
461243830Sdim            << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
462193323Sed        IsError = true;
463234353Sdim      }
464234353Sdim      P.ConsumeToken();
465234353Sdim      SourceLocation RLoc;
466234353Sdim      SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
467234353Sdim      if (SimdLen.isInvalid())
468193323Sed        IsError = true;
469193323Sed    } else {
470193323Sed      OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
471193323Sed      if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
472193323Sed          CKind == OMPC_linear) {
473193323Sed        Parser::OpenMPVarListDataTy Data;
474193323Sed        auto *Vars = &Uniforms;
475193323Sed        if (CKind == OMPC_aligned)
476193323Sed          Vars = &Aligneds;
477193323Sed        else if (CKind == OMPC_linear)
478193323Sed          Vars = &Linears;
479193323Sed
480193323Sed        P.ConsumeToken();
481193323Sed        if (P.ParseOpenMPVarList(OMPD_declare_simd,
482193323Sed                                 getOpenMPClauseKind(ClauseName), *Vars, Data))
483193323Sed          IsError = true;
484193323Sed        if (CKind == OMPC_aligned)
485193323Sed          Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
486193323Sed        else if (CKind == OMPC_linear) {
487193323Sed          if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
488193323Sed                                                       Data.DepLinMapLoc))
489218893Sdim            Data.LinKind = OMPC_LINEAR_val;
490218893Sdim          LinModifiers.append(Linears.size() - LinModifiers.size(),
491193323Sed                              Data.LinKind);
492218893Sdim          Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
493218893Sdim        }
494193323Sed      } else
495193323Sed        // TODO: add parsing of other clauses.
496193323Sed        break;
497212904Sdim    }
498212904Sdim    // Skip ',' if any.
499193323Sed    if (Tok.is(tok::comma))
500193323Sed      P.ConsumeToken();
501193323Sed  }
502193323Sed  return IsError;
503193323Sed}
504193323Sed
505203954Srdivacky/// Parse clauses for '#pragma omp declare simd'.
506193323SedParser::DeclGroupPtrTy
507193323SedParser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
508193323Sed                                   CachedTokens &Toks, SourceLocation Loc) {
509193323Sed  PP.EnterToken(Tok);
510193323Sed  PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
511193323Sed  // Consume the previously pushed token.
512193323Sed  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
513193323Sed
514193323Sed  FNContextRAII FnContext(*this, Ptr);
515193323Sed  OMPDeclareSimdDeclAttr::BranchStateTy BS =
516193323Sed      OMPDeclareSimdDeclAttr::BS_Undefined;
517193323Sed  ExprResult Simdlen;
518212904Sdim  SmallVector<Expr *, 4> Uniforms;
519193323Sed  SmallVector<Expr *, 4> Aligneds;
520193323Sed  SmallVector<Expr *, 4> Alignments;
521193323Sed  SmallVector<Expr *, 4> Linears;
522212904Sdim  SmallVector<unsigned, 4> LinModifiers;
523212904Sdim  SmallVector<Expr *, 4> Steps;
524193323Sed  bool IsError =
525193323Sed      parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
526193323Sed                              Alignments, Linears, LinModifiers, Steps);
527193323Sed  // Need to check for extra tokens.
528193323Sed  if (Tok.isNot(tok::annot_pragma_openmp_end)) {
529193323Sed    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
530193323Sed        << getOpenMPDirectiveName(OMPD_declare_simd);
531193323Sed    while (Tok.isNot(tok::annot_pragma_openmp_end))
532193323Sed      ConsumeAnyToken();
533193323Sed  }
534193323Sed  // Skip the last annot_pragma_openmp_end.
535193323Sed  SourceLocation EndLoc = ConsumeToken();
536193323Sed  if (!IsError) {
537193323Sed    return Actions.ActOnOpenMPDeclareSimdDirective(
538193323Sed        Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
539193323Sed        LinModifiers, Steps, SourceRange(Loc, EndLoc));
540193323Sed  }
541218893Sdim  return Ptr;
542193323Sed}
543193323Sed
544193323Sed/// \brief Parsing of declarative OpenMP directives.
545212904Sdim///
546218893Sdim///       threadprivate-directive:
547193323Sed///         annot_pragma_openmp 'threadprivate' simple-variable-list
548193323Sed///         annot_pragma_openmp_end
549193323Sed///
550193323Sed///       declare-reduction-directive:
551218893Sdim///        annot_pragma_openmp 'declare' 'reduction' [...]
552218893Sdim///        annot_pragma_openmp_end
553193323Sed///
554212904Sdim///       declare-simd-directive:
555193323Sed///         annot_pragma_openmp 'declare simd' {<clause> [,]}
556212904Sdim///         annot_pragma_openmp_end
557193323Sed///         <function declaration/definition>
558193323Sed///
559193323SedParser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
560193323Sed    AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
561218893Sdim    DeclSpec::TST TagType, Decl *Tag) {
562193323Sed  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
563193323Sed  ParenBraceBracketBalancer BalancerRAIIObj(*this);
564193323Sed
565193323Sed  SourceLocation Loc = ConsumeToken();
566193323Sed  auto DKind = ParseOpenMPDirectiveKind(*this);
567193323Sed
568193323Sed  switch (DKind) {
569193323Sed  case OMPD_threadprivate: {
570193323Sed    ConsumeToken();
571193323Sed    ThreadprivateListParserHelper Helper(this);
572193323Sed    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
573193323Sed      // The last seen token is annot_pragma_openmp_end - need to check for
574193323Sed      // extra tokens.
575212904Sdim      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
576193323Sed        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
577193323Sed            << getOpenMPDirectiveName(OMPD_threadprivate);
578193323Sed        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
579193323Sed      }
580193323Sed      // Skip the last annot_pragma_openmp_end.
581193323Sed      ConsumeToken();
582193323Sed      return Actions.ActOnOpenMPThreadprivateDirective(Loc,
583193323Sed                                                       Helper.getIdentifiers());
584193323Sed    }
585193323Sed    break;
586193323Sed  }
587193323Sed  case OMPD_declare_reduction:
588193323Sed    ConsumeToken();
589193323Sed    if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
590193323Sed      // The last seen token is annot_pragma_openmp_end - need to check for
591193323Sed      // extra tokens.
592193323Sed      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
593193323Sed        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
594193323Sed            << getOpenMPDirectiveName(OMPD_declare_reduction);
595193323Sed        while (Tok.isNot(tok::annot_pragma_openmp_end))
596193323Sed          ConsumeAnyToken();
597193323Sed      }
598218893Sdim      // Skip the last annot_pragma_openmp_end.
599218893Sdim      ConsumeToken();
600218893Sdim      return Res;
601218893Sdim    }
602218893Sdim    break;
603221345Sdim  case OMPD_declare_simd: {
604218893Sdim    // The syntax is:
605218893Sdim    // { #pragma omp declare simd }
606218893Sdim    // <function-declaration-or-definition>
607218893Sdim    //
608    ConsumeToken();
609    CachedTokens Toks;
610    while(Tok.isNot(tok::annot_pragma_openmp_end)) {
611      Toks.push_back(Tok);
612      ConsumeAnyToken();
613    }
614    Toks.push_back(Tok);
615    ConsumeAnyToken();
616
617    DeclGroupPtrTy Ptr;
618    if (Tok.is(tok::annot_pragma_openmp))
619      Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
620    else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
621      // Here we expect to see some function declaration.
622      if (AS == AS_none) {
623        assert(TagType == DeclSpec::TST_unspecified);
624        MaybeParseCXX11Attributes(Attrs);
625        ParsingDeclSpec PDS(*this);
626        Ptr = ParseExternalDeclaration(Attrs, &PDS);
627      } else {
628        Ptr =
629            ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
630      }
631    }
632    if (!Ptr) {
633      Diag(Loc, diag::err_omp_decl_in_declare_simd);
634      return DeclGroupPtrTy();
635    }
636    return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
637  }
638  case OMPD_declare_target: {
639    SourceLocation DTLoc = ConsumeAnyToken();
640    if (Tok.isNot(tok::annot_pragma_openmp_end)) {
641      // OpenMP 4.5 syntax with list of entities.
642      llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls;
643      while (Tok.isNot(tok::annot_pragma_openmp_end)) {
644        OMPDeclareTargetDeclAttr::MapTypeTy MT =
645            OMPDeclareTargetDeclAttr::MT_To;
646        if (Tok.is(tok::identifier)) {
647          IdentifierInfo *II = Tok.getIdentifierInfo();
648          StringRef ClauseName = II->getName();
649          // Parse 'to|link' clauses.
650          if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
651                                                               MT)) {
652            Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
653                << ClauseName;
654            break;
655          }
656          ConsumeToken();
657        }
658        auto Callback = [this, MT, &SameDirectiveDecls](
659            CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
660          Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT,
661                                               SameDirectiveDecls);
662        };
663        if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true))
664          break;
665
666        // Consume optional ','.
667        if (Tok.is(tok::comma))
668          ConsumeToken();
669      }
670      SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
671      ConsumeAnyToken();
672      return DeclGroupPtrTy();
673    }
674
675    // Skip the last annot_pragma_openmp_end.
676    ConsumeAnyToken();
677
678    if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
679      return DeclGroupPtrTy();
680
681    DKind = ParseOpenMPDirectiveKind(*this);
682    while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
683           Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) {
684      ParsedAttributesWithRange attrs(AttrFactory);
685      MaybeParseCXX11Attributes(attrs);
686      ParseExternalDeclaration(attrs);
687      if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
688        TentativeParsingAction TPA(*this);
689        ConsumeToken();
690        DKind = ParseOpenMPDirectiveKind(*this);
691        if (DKind != OMPD_end_declare_target)
692          TPA.Revert();
693        else
694          TPA.Commit();
695      }
696    }
697
698    if (DKind == OMPD_end_declare_target) {
699      ConsumeAnyToken();
700      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
701        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
702            << getOpenMPDirectiveName(OMPD_end_declare_target);
703        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
704      }
705      // Skip the last annot_pragma_openmp_end.
706      ConsumeAnyToken();
707    } else {
708      Diag(Tok, diag::err_expected_end_declare_target);
709      Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
710    }
711    Actions.ActOnFinishOpenMPDeclareTargetDirective();
712    return DeclGroupPtrTy();
713  }
714  case OMPD_unknown:
715    Diag(Tok, diag::err_omp_unknown_directive);
716    break;
717  case OMPD_parallel:
718  case OMPD_simd:
719  case OMPD_task:
720  case OMPD_taskyield:
721  case OMPD_barrier:
722  case OMPD_taskwait:
723  case OMPD_taskgroup:
724  case OMPD_flush:
725  case OMPD_for:
726  case OMPD_for_simd:
727  case OMPD_sections:
728  case OMPD_section:
729  case OMPD_single:
730  case OMPD_master:
731  case OMPD_ordered:
732  case OMPD_critical:
733  case OMPD_parallel_for:
734  case OMPD_parallel_for_simd:
735  case OMPD_parallel_sections:
736  case OMPD_atomic:
737  case OMPD_target:
738  case OMPD_teams:
739  case OMPD_cancellation_point:
740  case OMPD_cancel:
741  case OMPD_target_data:
742  case OMPD_target_enter_data:
743  case OMPD_target_exit_data:
744  case OMPD_target_parallel:
745  case OMPD_target_parallel_for:
746  case OMPD_taskloop:
747  case OMPD_taskloop_simd:
748  case OMPD_distribute:
749  case OMPD_end_declare_target:
750  case OMPD_target_update:
751  case OMPD_distribute_parallel_for:
752  case OMPD_distribute_parallel_for_simd:
753  case OMPD_distribute_simd:
754  case OMPD_target_parallel_for_simd:
755  case OMPD_target_simd:
756  case OMPD_teams_distribute:
757  case OMPD_teams_distribute_simd:
758  case OMPD_teams_distribute_parallel_for_simd:
759  case OMPD_teams_distribute_parallel_for:
760  case OMPD_target_teams:
761  case OMPD_target_teams_distribute:
762  case OMPD_target_teams_distribute_parallel_for:
763  case OMPD_target_teams_distribute_parallel_for_simd:
764  case OMPD_target_teams_distribute_simd:
765    Diag(Tok, diag::err_omp_unexpected_directive)
766        << getOpenMPDirectiveName(DKind);
767    break;
768  }
769  while (Tok.isNot(tok::annot_pragma_openmp_end))
770    ConsumeAnyToken();
771  ConsumeAnyToken();
772  return nullptr;
773}
774
775/// \brief Parsing of declarative or executable OpenMP directives.
776///
777///       threadprivate-directive:
778///         annot_pragma_openmp 'threadprivate' simple-variable-list
779///         annot_pragma_openmp_end
780///
781///       declare-reduction-directive:
782///         annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
783///         <type> {',' <type>} ':' <expression> ')' ['initializer' '('
784///         ('omp_priv' '=' <expression>|<function_call>) ')']
785///         annot_pragma_openmp_end
786///
787///       executable-directive:
788///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
789///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
790///         'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
791///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
792///         'for simd' | 'parallel for simd' | 'target' | 'target data' |
793///         'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
794///         'distribute' | 'target enter data' | 'target exit data' |
795///         'target parallel' | 'target parallel for' |
796///         'target update' | 'distribute parallel for' |
797///         'distribute paralle for simd' | 'distribute simd' |
798///         'target parallel for simd' | 'target simd' |
799///         'teams distribute' | 'teams distribute simd' |
800///         'teams distribute parallel for simd' |
801///         'teams distribute parallel for' | 'target teams' |
802///         'target teams distribute' |
803///         'target teams distribute parallel for' |
804///         'target teams distribute parallel for simd' |
805///         'target teams distribute simd' {clause}
806///         annot_pragma_openmp_end
807///
808StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
809    AllowedContsructsKind Allowed) {
810  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
811  ParenBraceBracketBalancer BalancerRAIIObj(*this);
812  SmallVector<OMPClause *, 5> Clauses;
813  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
814  FirstClauses(OMPC_unknown + 1);
815  unsigned ScopeFlags =
816      Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
817  SourceLocation Loc = ConsumeToken(), EndLoc;
818  auto DKind = ParseOpenMPDirectiveKind(*this);
819  OpenMPDirectiveKind CancelRegion = OMPD_unknown;
820  // Name of critical directive.
821  DeclarationNameInfo DirName;
822  StmtResult Directive = StmtError();
823  bool HasAssociatedStatement = true;
824  bool FlushHasClause = false;
825
826  switch (DKind) {
827  case OMPD_threadprivate: {
828    if (Allowed != ACK_Any) {
829      Diag(Tok, diag::err_omp_immediate_directive)
830          << getOpenMPDirectiveName(DKind) << 0;
831    }
832    ConsumeToken();
833    ThreadprivateListParserHelper Helper(this);
834    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
835      // The last seen token is annot_pragma_openmp_end - need to check for
836      // extra tokens.
837      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
838        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
839            << getOpenMPDirectiveName(OMPD_threadprivate);
840        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
841      }
842      DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
843          Loc, Helper.getIdentifiers());
844      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
845    }
846    SkipUntil(tok::annot_pragma_openmp_end);
847    break;
848  }
849  case OMPD_declare_reduction:
850    ConsumeToken();
851    if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
852      // The last seen token is annot_pragma_openmp_end - need to check for
853      // extra tokens.
854      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
855        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
856            << getOpenMPDirectiveName(OMPD_declare_reduction);
857        while (Tok.isNot(tok::annot_pragma_openmp_end))
858          ConsumeAnyToken();
859      }
860      ConsumeAnyToken();
861      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
862    } else
863      SkipUntil(tok::annot_pragma_openmp_end);
864    break;
865  case OMPD_flush:
866    if (PP.LookAhead(0).is(tok::l_paren)) {
867      FlushHasClause = true;
868      // Push copy of the current token back to stream to properly parse
869      // pseudo-clause OMPFlushClause.
870      PP.EnterToken(Tok);
871    }
872  case OMPD_taskyield:
873  case OMPD_barrier:
874  case OMPD_taskwait:
875  case OMPD_cancellation_point:
876  case OMPD_cancel:
877  case OMPD_target_enter_data:
878  case OMPD_target_exit_data:
879  case OMPD_target_update:
880    if (Allowed == ACK_StatementsOpenMPNonStandalone) {
881      Diag(Tok, diag::err_omp_immediate_directive)
882          << getOpenMPDirectiveName(DKind) << 0;
883    }
884    HasAssociatedStatement = false;
885    // Fall through for further analysis.
886  case OMPD_parallel:
887  case OMPD_simd:
888  case OMPD_for:
889  case OMPD_for_simd:
890  case OMPD_sections:
891  case OMPD_single:
892  case OMPD_section:
893  case OMPD_master:
894  case OMPD_critical:
895  case OMPD_parallel_for:
896  case OMPD_parallel_for_simd:
897  case OMPD_parallel_sections:
898  case OMPD_task:
899  case OMPD_ordered:
900  case OMPD_atomic:
901  case OMPD_target:
902  case OMPD_teams:
903  case OMPD_taskgroup:
904  case OMPD_target_data:
905  case OMPD_target_parallel:
906  case OMPD_target_parallel_for:
907  case OMPD_taskloop:
908  case OMPD_taskloop_simd:
909  case OMPD_distribute:
910  case OMPD_distribute_parallel_for:
911  case OMPD_distribute_parallel_for_simd:
912  case OMPD_distribute_simd:
913  case OMPD_target_parallel_for_simd:
914  case OMPD_target_simd:
915  case OMPD_teams_distribute:
916  case OMPD_teams_distribute_simd:
917  case OMPD_teams_distribute_parallel_for_simd:
918  case OMPD_teams_distribute_parallel_for:
919  case OMPD_target_teams:
920  case OMPD_target_teams_distribute:
921  case OMPD_target_teams_distribute_parallel_for:
922  case OMPD_target_teams_distribute_parallel_for_simd:
923  case OMPD_target_teams_distribute_simd: {
924    ConsumeToken();
925    // Parse directive name of the 'critical' directive if any.
926    if (DKind == OMPD_critical) {
927      BalancedDelimiterTracker T(*this, tok::l_paren,
928                                 tok::annot_pragma_openmp_end);
929      if (!T.consumeOpen()) {
930        if (Tok.isAnyIdentifier()) {
931          DirName =
932              DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
933          ConsumeAnyToken();
934        } else {
935          Diag(Tok, diag::err_omp_expected_identifier_for_critical);
936        }
937        T.consumeClose();
938      }
939    } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
940      CancelRegion = ParseOpenMPDirectiveKind(*this);
941      if (Tok.isNot(tok::annot_pragma_openmp_end))
942        ConsumeToken();
943    }
944
945    if (isOpenMPLoopDirective(DKind))
946      ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
947    if (isOpenMPSimdDirective(DKind))
948      ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
949    ParseScope OMPDirectiveScope(this, ScopeFlags);
950    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
951
952    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
953      OpenMPClauseKind CKind =
954          Tok.isAnnotation()
955              ? OMPC_unknown
956              : FlushHasClause ? OMPC_flush
957                               : getOpenMPClauseKind(PP.getSpelling(Tok));
958      Actions.StartOpenMPClause(CKind);
959      FlushHasClause = false;
960      OMPClause *Clause =
961          ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
962      FirstClauses[CKind].setInt(true);
963      if (Clause) {
964        FirstClauses[CKind].setPointer(Clause);
965        Clauses.push_back(Clause);
966      }
967
968      // Skip ',' if any.
969      if (Tok.is(tok::comma))
970        ConsumeToken();
971      Actions.EndOpenMPClause();
972    }
973    // End location of the directive.
974    EndLoc = Tok.getLocation();
975    // Consume final annot_pragma_openmp_end.
976    ConsumeToken();
977
978    // OpenMP [2.13.8, ordered Construct, Syntax]
979    // If the depend clause is specified, the ordered construct is a stand-alone
980    // directive.
981    if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
982      if (Allowed == ACK_StatementsOpenMPNonStandalone) {
983        Diag(Loc, diag::err_omp_immediate_directive)
984            << getOpenMPDirectiveName(DKind) << 1
985            << getOpenMPClauseName(OMPC_depend);
986      }
987      HasAssociatedStatement = false;
988    }
989
990    StmtResult AssociatedStmt;
991    if (HasAssociatedStatement) {
992      // The body is a block scope like in Lambdas and Blocks.
993      Sema::CompoundScopeRAII CompoundScope(Actions);
994      Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
995      Actions.ActOnStartOfCompoundStmt();
996      // Parse statement
997      AssociatedStmt = ParseStatement();
998      Actions.ActOnFinishOfCompoundStmt();
999      AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1000    }
1001    Directive = Actions.ActOnOpenMPExecutableDirective(
1002        DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1003        EndLoc);
1004
1005    // Exit scope.
1006    Actions.EndOpenMPDSABlock(Directive.get());
1007    OMPDirectiveScope.Exit();
1008    break;
1009  }
1010  case OMPD_declare_simd:
1011  case OMPD_declare_target:
1012  case OMPD_end_declare_target:
1013    Diag(Tok, diag::err_omp_unexpected_directive)
1014        << getOpenMPDirectiveName(DKind);
1015    SkipUntil(tok::annot_pragma_openmp_end);
1016    break;
1017  case OMPD_unknown:
1018    Diag(Tok, diag::err_omp_unknown_directive);
1019    SkipUntil(tok::annot_pragma_openmp_end);
1020    break;
1021  }
1022  return Directive;
1023}
1024
1025// Parses simple list:
1026//   simple-variable-list:
1027//         '(' id-expression {, id-expression} ')'
1028//
1029bool Parser::ParseOpenMPSimpleVarList(
1030    OpenMPDirectiveKind Kind,
1031    const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
1032        Callback,
1033    bool AllowScopeSpecifier) {
1034  // Parse '('.
1035  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1036  if (T.expectAndConsume(diag::err_expected_lparen_after,
1037                         getOpenMPDirectiveName(Kind)))
1038    return true;
1039  bool IsCorrect = true;
1040  bool NoIdentIsFound = true;
1041
1042  // Read tokens while ')' or annot_pragma_openmp_end is not found.
1043  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
1044    CXXScopeSpec SS;
1045    SourceLocation TemplateKWLoc;
1046    UnqualifiedId Name;
1047    // Read var name.
1048    Token PrevTok = Tok;
1049    NoIdentIsFound = false;
1050
1051    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
1052        ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
1053      IsCorrect = false;
1054      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1055                StopBeforeMatch);
1056    } else if (ParseUnqualifiedId(SS, false, false, false, nullptr,
1057                                  TemplateKWLoc, Name)) {
1058      IsCorrect = false;
1059      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1060                StopBeforeMatch);
1061    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
1062               Tok.isNot(tok::annot_pragma_openmp_end)) {
1063      IsCorrect = false;
1064      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1065                StopBeforeMatch);
1066      Diag(PrevTok.getLocation(), diag::err_expected)
1067          << tok::identifier
1068          << SourceRange(PrevTok.getLocation(), PrevTokLocation);
1069    } else {
1070      Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1071    }
1072    // Consume ','.
1073    if (Tok.is(tok::comma)) {
1074      ConsumeToken();
1075    }
1076  }
1077
1078  if (NoIdentIsFound) {
1079    Diag(Tok, diag::err_expected) << tok::identifier;
1080    IsCorrect = false;
1081  }
1082
1083  // Parse ')'.
1084  IsCorrect = !T.consumeClose() && IsCorrect;
1085
1086  return !IsCorrect;
1087}
1088
1089/// \brief Parsing of OpenMP clauses.
1090///
1091///    clause:
1092///       if-clause | final-clause | num_threads-clause | safelen-clause |
1093///       default-clause | private-clause | firstprivate-clause | shared-clause
1094///       | linear-clause | aligned-clause | collapse-clause |
1095///       lastprivate-clause | reduction-clause | proc_bind-clause |
1096///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
1097///       mergeable-clause | flush-clause | read-clause | write-clause |
1098///       update-clause | capture-clause | seq_cst-clause | device-clause |
1099///       simdlen-clause | threads-clause | simd-clause | num_teams-clause |
1100///       thread_limit-clause | priority-clause | grainsize-clause |
1101///       nogroup-clause | num_tasks-clause | hint-clause | to-clause |
1102///       from-clause | is_device_ptr-clause
1103///
1104OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
1105                                     OpenMPClauseKind CKind, bool FirstClause) {
1106  OMPClause *Clause = nullptr;
1107  bool ErrorFound = false;
1108  // Check if clause is allowed for the given directive.
1109  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
1110    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1111                                               << getOpenMPDirectiveName(DKind);
1112    ErrorFound = true;
1113  }
1114
1115  switch (CKind) {
1116  case OMPC_final:
1117  case OMPC_num_threads:
1118  case OMPC_safelen:
1119  case OMPC_simdlen:
1120  case OMPC_collapse:
1121  case OMPC_ordered:
1122  case OMPC_device:
1123  case OMPC_num_teams:
1124  case OMPC_thread_limit:
1125  case OMPC_priority:
1126  case OMPC_grainsize:
1127  case OMPC_num_tasks:
1128  case OMPC_hint:
1129    // OpenMP [2.5, Restrictions]
1130    //  At most one num_threads clause can appear on the directive.
1131    // OpenMP [2.8.1, simd construct, Restrictions]
1132    //  Only one safelen  clause can appear on a simd directive.
1133    //  Only one simdlen  clause can appear on a simd directive.
1134    //  Only one collapse clause can appear on a simd directive.
1135    // OpenMP [2.9.1, target data construct, Restrictions]
1136    //  At most one device clause can appear on the directive.
1137    // OpenMP [2.11.1, task Construct, Restrictions]
1138    //  At most one if clause can appear on the directive.
1139    //  At most one final clause can appear on the directive.
1140    // OpenMP [teams Construct, Restrictions]
1141    //  At most one num_teams clause can appear on the directive.
1142    //  At most one thread_limit clause can appear on the directive.
1143    // OpenMP [2.9.1, task Construct, Restrictions]
1144    // At most one priority clause can appear on the directive.
1145    // OpenMP [2.9.2, taskloop Construct, Restrictions]
1146    // At most one grainsize clause can appear on the directive.
1147    // OpenMP [2.9.2, taskloop Construct, Restrictions]
1148    // At most one num_tasks clause can appear on the directive.
1149    if (!FirstClause) {
1150      Diag(Tok, diag::err_omp_more_one_clause)
1151          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1152      ErrorFound = true;
1153    }
1154
1155    if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
1156      Clause = ParseOpenMPClause(CKind);
1157    else
1158      Clause = ParseOpenMPSingleExprClause(CKind);
1159    break;
1160  case OMPC_default:
1161  case OMPC_proc_bind:
1162    // OpenMP [2.14.3.1, Restrictions]
1163    //  Only a single default clause may be specified on a parallel, task or
1164    //  teams directive.
1165    // OpenMP [2.5, parallel Construct, Restrictions]
1166    //  At most one proc_bind clause can appear on the directive.
1167    if (!FirstClause) {
1168      Diag(Tok, diag::err_omp_more_one_clause)
1169          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1170      ErrorFound = true;
1171    }
1172
1173    Clause = ParseOpenMPSimpleClause(CKind);
1174    break;
1175  case OMPC_schedule:
1176  case OMPC_dist_schedule:
1177  case OMPC_defaultmap:
1178    // OpenMP [2.7.1, Restrictions, p. 3]
1179    //  Only one schedule clause can appear on a loop directive.
1180    // OpenMP [2.10.4, Restrictions, p. 106]
1181    //  At most one defaultmap clause can appear on the directive.
1182    if (!FirstClause) {
1183      Diag(Tok, diag::err_omp_more_one_clause)
1184          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1185      ErrorFound = true;
1186    }
1187
1188  case OMPC_if:
1189    Clause = ParseOpenMPSingleExprWithArgClause(CKind);
1190    break;
1191  case OMPC_nowait:
1192  case OMPC_untied:
1193  case OMPC_mergeable:
1194  case OMPC_read:
1195  case OMPC_write:
1196  case OMPC_update:
1197  case OMPC_capture:
1198  case OMPC_seq_cst:
1199  case OMPC_threads:
1200  case OMPC_simd:
1201  case OMPC_nogroup:
1202    // OpenMP [2.7.1, Restrictions, p. 9]
1203    //  Only one ordered clause can appear on a loop directive.
1204    // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
1205    //  Only one nowait clause can appear on a for directive.
1206    if (!FirstClause) {
1207      Diag(Tok, diag::err_omp_more_one_clause)
1208          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
1209      ErrorFound = true;
1210    }
1211
1212    Clause = ParseOpenMPClause(CKind);
1213    break;
1214  case OMPC_private:
1215  case OMPC_firstprivate:
1216  case OMPC_lastprivate:
1217  case OMPC_shared:
1218  case OMPC_reduction:
1219  case OMPC_linear:
1220  case OMPC_aligned:
1221  case OMPC_copyin:
1222  case OMPC_copyprivate:
1223  case OMPC_flush:
1224  case OMPC_depend:
1225  case OMPC_map:
1226  case OMPC_to:
1227  case OMPC_from:
1228  case OMPC_use_device_ptr:
1229  case OMPC_is_device_ptr:
1230    Clause = ParseOpenMPVarListClause(DKind, CKind);
1231    break;
1232  case OMPC_unknown:
1233    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1234        << getOpenMPDirectiveName(DKind);
1235    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1236    break;
1237  case OMPC_threadprivate:
1238  case OMPC_uniform:
1239    Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
1240                                               << getOpenMPDirectiveName(DKind);
1241    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
1242    break;
1243  }
1244  return ErrorFound ? nullptr : Clause;
1245}
1246
1247/// Parses simple expression in parens for single-expression clauses of OpenMP
1248/// constructs.
1249/// \param RLoc Returned location of right paren.
1250ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
1251                                         SourceLocation &RLoc) {
1252  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1253  if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1254    return ExprError();
1255
1256  SourceLocation ELoc = Tok.getLocation();
1257  ExprResult LHS(ParseCastExpression(
1258      /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast));
1259  ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
1260  Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1261
1262  // Parse ')'.
1263  T.consumeClose();
1264
1265  RLoc = T.getCloseLocation();
1266  return Val;
1267}
1268
1269/// \brief Parsing of OpenMP clauses with single expressions like 'final',
1270/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
1271/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
1272///
1273///    final-clause:
1274///      'final' '(' expression ')'
1275///
1276///    num_threads-clause:
1277///      'num_threads' '(' expression ')'
1278///
1279///    safelen-clause:
1280///      'safelen' '(' expression ')'
1281///
1282///    simdlen-clause:
1283///      'simdlen' '(' expression ')'
1284///
1285///    collapse-clause:
1286///      'collapse' '(' expression ')'
1287///
1288///    priority-clause:
1289///      'priority' '(' expression ')'
1290///
1291///    grainsize-clause:
1292///      'grainsize' '(' expression ')'
1293///
1294///    num_tasks-clause:
1295///      'num_tasks' '(' expression ')'
1296///
1297///    hint-clause:
1298///      'hint' '(' expression ')'
1299///
1300OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
1301  SourceLocation Loc = ConsumeToken();
1302  SourceLocation LLoc = Tok.getLocation();
1303  SourceLocation RLoc;
1304
1305  ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
1306
1307  if (Val.isInvalid())
1308    return nullptr;
1309
1310  return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
1311}
1312
1313/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
1314///
1315///    default-clause:
1316///         'default' '(' 'none' | 'shared' ')
1317///
1318///    proc_bind-clause:
1319///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
1320///
1321OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
1322  SourceLocation Loc = Tok.getLocation();
1323  SourceLocation LOpen = ConsumeToken();
1324  // Parse '('.
1325  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1326  if (T.expectAndConsume(diag::err_expected_lparen_after,
1327                         getOpenMPClauseName(Kind)))
1328    return nullptr;
1329
1330  unsigned Type = getOpenMPSimpleClauseType(
1331      Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1332  SourceLocation TypeLoc = Tok.getLocation();
1333  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1334      Tok.isNot(tok::annot_pragma_openmp_end))
1335    ConsumeAnyToken();
1336
1337  // Parse ')'.
1338  T.consumeClose();
1339
1340  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
1341                                         Tok.getLocation());
1342}
1343
1344/// \brief Parsing of OpenMP clauses like 'ordered'.
1345///
1346///    ordered-clause:
1347///         'ordered'
1348///
1349///    nowait-clause:
1350///         'nowait'
1351///
1352///    untied-clause:
1353///         'untied'
1354///
1355///    mergeable-clause:
1356///         'mergeable'
1357///
1358///    read-clause:
1359///         'read'
1360///
1361///    threads-clause:
1362///         'threads'
1363///
1364///    simd-clause:
1365///         'simd'
1366///
1367///    nogroup-clause:
1368///         'nogroup'
1369///
1370OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
1371  SourceLocation Loc = Tok.getLocation();
1372  ConsumeAnyToken();
1373
1374  return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
1375}
1376
1377
1378/// \brief Parsing of OpenMP clauses with single expressions and some additional
1379/// argument like 'schedule' or 'dist_schedule'.
1380///
1381///    schedule-clause:
1382///      'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
1383///      ')'
1384///
1385///    if-clause:
1386///      'if' '(' [ directive-name-modifier ':' ] expression ')'
1387///
1388///    defaultmap:
1389///      'defaultmap' '(' modifier ':' kind ')'
1390///
1391OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
1392  SourceLocation Loc = ConsumeToken();
1393  SourceLocation DelimLoc;
1394  // Parse '('.
1395  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1396  if (T.expectAndConsume(diag::err_expected_lparen_after,
1397                         getOpenMPClauseName(Kind)))
1398    return nullptr;
1399
1400  ExprResult Val;
1401  SmallVector<unsigned, 4> Arg;
1402  SmallVector<SourceLocation, 4> KLoc;
1403  if (Kind == OMPC_schedule) {
1404    enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1405    Arg.resize(NumberOfElements);
1406    KLoc.resize(NumberOfElements);
1407    Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
1408    Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
1409    Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
1410    auto KindModifier = getOpenMPSimpleClauseType(
1411        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1412    if (KindModifier > OMPC_SCHEDULE_unknown) {
1413      // Parse 'modifier'
1414      Arg[Modifier1] = KindModifier;
1415      KLoc[Modifier1] = Tok.getLocation();
1416      if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1417          Tok.isNot(tok::annot_pragma_openmp_end))
1418        ConsumeAnyToken();
1419      if (Tok.is(tok::comma)) {
1420        // Parse ',' 'modifier'
1421        ConsumeAnyToken();
1422        KindModifier = getOpenMPSimpleClauseType(
1423            Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1424        Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
1425                             ? KindModifier
1426                             : (unsigned)OMPC_SCHEDULE_unknown;
1427        KLoc[Modifier2] = Tok.getLocation();
1428        if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1429            Tok.isNot(tok::annot_pragma_openmp_end))
1430          ConsumeAnyToken();
1431      }
1432      // Parse ':'
1433      if (Tok.is(tok::colon))
1434        ConsumeAnyToken();
1435      else
1436        Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
1437      KindModifier = getOpenMPSimpleClauseType(
1438          Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
1439    }
1440    Arg[ScheduleKind] = KindModifier;
1441    KLoc[ScheduleKind] = Tok.getLocation();
1442    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1443        Tok.isNot(tok::annot_pragma_openmp_end))
1444      ConsumeAnyToken();
1445    if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1446         Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1447         Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1448        Tok.is(tok::comma))
1449      DelimLoc = ConsumeAnyToken();
1450  } else if (Kind == OMPC_dist_schedule) {
1451    Arg.push_back(getOpenMPSimpleClauseType(
1452        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1453    KLoc.push_back(Tok.getLocation());
1454    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1455        Tok.isNot(tok::annot_pragma_openmp_end))
1456      ConsumeAnyToken();
1457    if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
1458      DelimLoc = ConsumeAnyToken();
1459  } else if (Kind == OMPC_defaultmap) {
1460    // Get a defaultmap modifier
1461    Arg.push_back(getOpenMPSimpleClauseType(
1462        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1463    KLoc.push_back(Tok.getLocation());
1464    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1465        Tok.isNot(tok::annot_pragma_openmp_end))
1466      ConsumeAnyToken();
1467    // Parse ':'
1468    if (Tok.is(tok::colon))
1469      ConsumeAnyToken();
1470    else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
1471      Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
1472    // Get a defaultmap kind
1473    Arg.push_back(getOpenMPSimpleClauseType(
1474        Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
1475    KLoc.push_back(Tok.getLocation());
1476    if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
1477        Tok.isNot(tok::annot_pragma_openmp_end))
1478      ConsumeAnyToken();
1479  } else {
1480    assert(Kind == OMPC_if);
1481    KLoc.push_back(Tok.getLocation());
1482    TentativeParsingAction TPA(*this);
1483    Arg.push_back(ParseOpenMPDirectiveKind(*this));
1484    if (Arg.back() != OMPD_unknown) {
1485      ConsumeToken();
1486      if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
1487        TPA.Commit();
1488        DelimLoc = ConsumeToken();
1489      } else {
1490        TPA.Revert();
1491        Arg.back() = OMPD_unknown;
1492      }
1493    } else
1494      TPA.Revert();
1495  }
1496
1497  bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
1498                          (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
1499                          Kind == OMPC_if;
1500  if (NeedAnExpression) {
1501    SourceLocation ELoc = Tok.getLocation();
1502    ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
1503    Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
1504    Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc);
1505  }
1506
1507  // Parse ')'.
1508  T.consumeClose();
1509
1510  if (NeedAnExpression && Val.isInvalid())
1511    return nullptr;
1512
1513  return Actions.ActOnOpenMPSingleExprWithArgClause(
1514      Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
1515      T.getCloseLocation());
1516}
1517
1518static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
1519                             UnqualifiedId &ReductionId) {
1520  SourceLocation TemplateKWLoc;
1521  if (ReductionIdScopeSpec.isEmpty()) {
1522    auto OOK = OO_None;
1523    switch (P.getCurToken().getKind()) {
1524    case tok::plus:
1525      OOK = OO_Plus;
1526      break;
1527    case tok::minus:
1528      OOK = OO_Minus;
1529      break;
1530    case tok::star:
1531      OOK = OO_Star;
1532      break;
1533    case tok::amp:
1534      OOK = OO_Amp;
1535      break;
1536    case tok::pipe:
1537      OOK = OO_Pipe;
1538      break;
1539    case tok::caret:
1540      OOK = OO_Caret;
1541      break;
1542    case tok::ampamp:
1543      OOK = OO_AmpAmp;
1544      break;
1545    case tok::pipepipe:
1546      OOK = OO_PipePipe;
1547      break;
1548    default:
1549      break;
1550    }
1551    if (OOK != OO_None) {
1552      SourceLocation OpLoc = P.ConsumeToken();
1553      SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
1554      ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
1555      return false;
1556    }
1557  }
1558  return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
1559                              /*AllowDestructorName*/ false,
1560                              /*AllowConstructorName*/ false, nullptr,
1561                              TemplateKWLoc, ReductionId);
1562}
1563
1564/// Parses clauses with list.
1565bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
1566                                OpenMPClauseKind Kind,
1567                                SmallVectorImpl<Expr *> &Vars,
1568                                OpenMPVarListDataTy &Data) {
1569  UnqualifiedId UnqualifiedReductionId;
1570  bool InvalidReductionId = false;
1571  bool MapTypeModifierSpecified = false;
1572
1573  // Parse '('.
1574  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
1575  if (T.expectAndConsume(diag::err_expected_lparen_after,
1576                         getOpenMPClauseName(Kind)))
1577    return true;
1578
1579  bool NeedRParenForLinear = false;
1580  BalancedDelimiterTracker LinearT(*this, tok::l_paren,
1581                                  tok::annot_pragma_openmp_end);
1582  // Handle reduction-identifier for reduction clause.
1583  if (Kind == OMPC_reduction) {
1584    ColonProtectionRAIIObject ColonRAII(*this);
1585    if (getLangOpts().CPlusPlus)
1586      ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
1587                                     /*ObjectType=*/nullptr,
1588                                     /*EnteringContext=*/false);
1589    InvalidReductionId = ParseReductionId(*this, Data.ReductionIdScopeSpec,
1590                                          UnqualifiedReductionId);
1591    if (InvalidReductionId) {
1592      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1593                StopBeforeMatch);
1594    }
1595    if (Tok.is(tok::colon))
1596      Data.ColonLoc = ConsumeToken();
1597    else
1598      Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
1599    if (!InvalidReductionId)
1600      Data.ReductionId =
1601          Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
1602  } else if (Kind == OMPC_depend) {
1603  // Handle dependency type for depend clause.
1604    ColonProtectionRAIIObject ColonRAII(*this);
1605    Data.DepKind =
1606        static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
1607            Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
1608    Data.DepLinMapLoc = Tok.getLocation();
1609
1610    if (Data.DepKind == OMPC_DEPEND_unknown) {
1611      SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1612                StopBeforeMatch);
1613    } else {
1614      ConsumeToken();
1615      // Special processing for depend(source) clause.
1616      if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
1617        // Parse ')'.
1618        T.consumeClose();
1619        return false;
1620      }
1621    }
1622    if (Tok.is(tok::colon))
1623      Data.ColonLoc = ConsumeToken();
1624    else {
1625      Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
1626                                      : diag::warn_pragma_expected_colon)
1627          << "dependency type";
1628    }
1629  } else if (Kind == OMPC_linear) {
1630    // Try to parse modifier if any.
1631    if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
1632      Data.LinKind = static_cast<OpenMPLinearClauseKind>(
1633          getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
1634      Data.DepLinMapLoc = ConsumeToken();
1635      LinearT.consumeOpen();
1636      NeedRParenForLinear = true;
1637    }
1638  } else if (Kind == OMPC_map) {
1639    // Handle map type for map clause.
1640    ColonProtectionRAIIObject ColonRAII(*this);
1641
1642    /// The map clause modifier token can be either a identifier or the C++
1643    /// delete keyword.
1644    auto &&IsMapClauseModifierToken = [](const Token &Tok) -> bool {
1645      return Tok.isOneOf(tok::identifier, tok::kw_delete);
1646    };
1647
1648    // The first identifier may be a list item, a map-type or a
1649    // map-type-modifier. The map modifier can also be delete which has the same
1650    // spelling of the C++ delete keyword.
1651    Data.MapType =
1652        IsMapClauseModifierToken(Tok)
1653            ? static_cast<OpenMPMapClauseKind>(
1654                  getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1655            : OMPC_MAP_unknown;
1656    Data.DepLinMapLoc = Tok.getLocation();
1657    bool ColonExpected = false;
1658
1659    if (IsMapClauseModifierToken(Tok)) {
1660      if (PP.LookAhead(0).is(tok::colon)) {
1661        if (Data.MapType == OMPC_MAP_unknown)
1662          Diag(Tok, diag::err_omp_unknown_map_type);
1663        else if (Data.MapType == OMPC_MAP_always)
1664          Diag(Tok, diag::err_omp_map_type_missing);
1665        ConsumeToken();
1666      } else if (PP.LookAhead(0).is(tok::comma)) {
1667        if (IsMapClauseModifierToken(PP.LookAhead(1)) &&
1668            PP.LookAhead(2).is(tok::colon)) {
1669          Data.MapTypeModifier = Data.MapType;
1670          if (Data.MapTypeModifier != OMPC_MAP_always) {
1671            Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1672            Data.MapTypeModifier = OMPC_MAP_unknown;
1673          } else
1674            MapTypeModifierSpecified = true;
1675
1676          ConsumeToken();
1677          ConsumeToken();
1678
1679          Data.MapType =
1680              IsMapClauseModifierToken(Tok)
1681                  ? static_cast<OpenMPMapClauseKind>(
1682                        getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)))
1683                  : OMPC_MAP_unknown;
1684          if (Data.MapType == OMPC_MAP_unknown ||
1685              Data.MapType == OMPC_MAP_always)
1686            Diag(Tok, diag::err_omp_unknown_map_type);
1687          ConsumeToken();
1688        } else {
1689          Data.MapType = OMPC_MAP_tofrom;
1690          Data.IsMapTypeImplicit = true;
1691        }
1692      } else {
1693        Data.MapType = OMPC_MAP_tofrom;
1694        Data.IsMapTypeImplicit = true;
1695      }
1696    } else {
1697      Data.MapType = OMPC_MAP_tofrom;
1698      Data.IsMapTypeImplicit = true;
1699    }
1700
1701    if (Tok.is(tok::colon))
1702      Data.ColonLoc = ConsumeToken();
1703    else if (ColonExpected)
1704      Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
1705  }
1706
1707  bool IsComma =
1708      (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
1709      (Kind == OMPC_reduction && !InvalidReductionId) ||
1710      (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
1711       (!MapTypeModifierSpecified ||
1712        Data.MapTypeModifier == OMPC_MAP_always)) ||
1713      (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
1714  const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
1715  while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
1716                     Tok.isNot(tok::annot_pragma_openmp_end))) {
1717    ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
1718    // Parse variable
1719    ExprResult VarExpr =
1720        Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
1721    if (VarExpr.isUsable())
1722      Vars.push_back(VarExpr.get());
1723    else {
1724      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1725                StopBeforeMatch);
1726    }
1727    // Skip ',' if any
1728    IsComma = Tok.is(tok::comma);
1729    if (IsComma)
1730      ConsumeToken();
1731    else if (Tok.isNot(tok::r_paren) &&
1732             Tok.isNot(tok::annot_pragma_openmp_end) &&
1733             (!MayHaveTail || Tok.isNot(tok::colon)))
1734      Diag(Tok, diag::err_omp_expected_punc)
1735          << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
1736                                   : getOpenMPClauseName(Kind))
1737          << (Kind == OMPC_flush);
1738  }
1739
1740  // Parse ')' for linear clause with modifier.
1741  if (NeedRParenForLinear)
1742    LinearT.consumeClose();
1743
1744  // Parse ':' linear-step (or ':' alignment).
1745  const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
1746  if (MustHaveTail) {
1747    Data.ColonLoc = Tok.getLocation();
1748    SourceLocation ELoc = ConsumeToken();
1749    ExprResult Tail = ParseAssignmentExpression();
1750    Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc);
1751    if (Tail.isUsable())
1752      Data.TailExpr = Tail.get();
1753    else
1754      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1755                StopBeforeMatch);
1756  }
1757
1758  // Parse ')'.
1759  T.consumeClose();
1760  if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
1761       Vars.empty()) ||
1762      (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
1763      (MustHaveTail && !Data.TailExpr) || InvalidReductionId)
1764    return true;
1765  return false;
1766}
1767
1768/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
1769/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
1770///
1771///    private-clause:
1772///       'private' '(' list ')'
1773///    firstprivate-clause:
1774///       'firstprivate' '(' list ')'
1775///    lastprivate-clause:
1776///       'lastprivate' '(' list ')'
1777///    shared-clause:
1778///       'shared' '(' list ')'
1779///    linear-clause:
1780///       'linear' '(' linear-list [ ':' linear-step ] ')'
1781///    aligned-clause:
1782///       'aligned' '(' list [ ':' alignment ] ')'
1783///    reduction-clause:
1784///       'reduction' '(' reduction-identifier ':' list ')'
1785///    copyprivate-clause:
1786///       'copyprivate' '(' list ')'
1787///    flush-clause:
1788///       'flush' '(' list ')'
1789///    depend-clause:
1790///       'depend' '(' in | out | inout : list | source ')'
1791///    map-clause:
1792///       'map' '(' [ [ always , ]
1793///          to | from | tofrom | alloc | release | delete ':' ] list ')';
1794///    to-clause:
1795///       'to' '(' list ')'
1796///    from-clause:
1797///       'from' '(' list ')'
1798///    use_device_ptr-clause:
1799///       'use_device_ptr' '(' list ')'
1800///    is_device_ptr-clause:
1801///       'is_device_ptr' '(' list ')'
1802///
1803/// For 'linear' clause linear-list may have the following forms:
1804///  list
1805///  modifier(list)
1806/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
1807OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
1808                                            OpenMPClauseKind Kind) {
1809  SourceLocation Loc = Tok.getLocation();
1810  SourceLocation LOpen = ConsumeToken();
1811  SmallVector<Expr *, 4> Vars;
1812  OpenMPVarListDataTy Data;
1813
1814  if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
1815    return nullptr;
1816
1817  return Actions.ActOnOpenMPVarListClause(
1818      Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(),
1819      Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
1820      Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
1821      Data.DepLinMapLoc);
1822}
1823
1824