ParseOpenMP.cpp revision 263509
1193326Sed//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed/// \file
10193326Sed/// \brief This file implements parsing of all OpenMP directives and clauses.
11193326Sed///
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "clang/AST/ASTConsumer.h"
15193326Sed#include "clang/AST/StmtOpenMP.h"
16212904Sdim#include "clang/Parse/ParseDiagnostic.h"
17212904Sdim#include "clang/Parse/Parser.h"
18212904Sdim#include "clang/Sema/Scope.h"
19200583Srdivacky#include "llvm/ADT/PointerIntPair.h"
20221345Sdim#include "RAIIObjectsForParser.h"
21221345Sdimusing namespace clang;
22193326Sed
23193326Sed//===----------------------------------------------------------------------===//
24193326Sed// OpenMP declarative directives.
25193326Sed//===----------------------------------------------------------------------===//
26212904Sdim
27193326Sed/// \brief Parsing of declarative OpenMP directives.
28193326Sed///
29226890Sdim///       threadprivate-directive:
30226890Sdim///         annot_pragma_openmp 'threadprivate' simple-variable-list
31226890Sdim///
32226890SdimParser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
33226890Sdim  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
34198092Srdivacky  ParenBraceBracketBalancer BalancerRAIIObj(*this);
35226890Sdim
36226890Sdim  SourceLocation Loc = ConsumeToken();
37226890Sdim  SmallVector<Expr *, 5> Identifiers;
38226890Sdim  OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
39193326Sed                                  OMPD_unknown :
40193326Sed                                  getOpenMPDirectiveKind(PP.getSpelling(Tok));
41198092Srdivacky
42198092Srdivacky  switch (DKind) {
43199990Srdivacky  case OMPD_threadprivate:
44198092Srdivacky    ConsumeToken();
45198092Srdivacky    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
46198092Srdivacky      // The last seen token is annot_pragma_openmp_end - need to check for
47198092Srdivacky      // extra tokens.
48198092Srdivacky      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
49198092Srdivacky        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
50198092Srdivacky          << getOpenMPDirectiveName(OMPD_threadprivate);
51198092Srdivacky        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
52198092Srdivacky      }
53198092Srdivacky      // Skip the last annot_pragma_openmp_end.
54198092Srdivacky      ConsumeToken();
55198092Srdivacky      return Actions.ActOnOpenMPThreadprivateDirective(Loc,
56198092Srdivacky                                                       Identifiers);
57198092Srdivacky    }
58198092Srdivacky    break;
59198092Srdivacky  case OMPD_unknown:
60198092Srdivacky    Diag(Tok, diag::err_omp_unknown_directive);
61198092Srdivacky    break;
62198092Srdivacky  case OMPD_parallel:
63198092Srdivacky  case OMPD_task:
64193326Sed  case NUM_OPENMP_DIRECTIVES:
65193326Sed    Diag(Tok, diag::err_omp_unexpected_directive)
66193326Sed      << getOpenMPDirectiveName(DKind);
67193326Sed    break;
68193326Sed  }
69193326Sed  SkipUntil(tok::annot_pragma_openmp_end);
70193326Sed  return DeclGroupPtrTy();
71193326Sed}
72193326Sed
73193326Sed/// \brief Parsing of declarative or executable OpenMP directives.
74193326Sed///
75193326Sed///       threadprivate-directive:
76193326Sed///         annot_pragma_openmp 'threadprivate' simple-variable-list
77193326Sed///         annot_pragma_openmp_end
78193326Sed///
79212904Sdim///       parallel-directive:
80193326Sed///         annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end
81193326Sed///
82226890SdimStmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
83226890Sdim  assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
84198092Srdivacky  ParenBraceBracketBalancer BalancerRAIIObj(*this);
85198092Srdivacky  SmallVector<Expr *, 5> Identifiers;
86198092Srdivacky  SmallVector<OMPClause *, 5> Clauses;
87193326Sed  SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES>
88193326Sed                                               FirstClauses(NUM_OPENMP_CLAUSES);
89193326Sed  const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
90212904Sdim                              Scope::OpenMPDirectiveScope;
91212904Sdim  SourceLocation Loc = ConsumeToken(), EndLoc;
92212904Sdim  OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
93212904Sdim                                  OMPD_unknown :
94193326Sed                                  getOpenMPDirectiveKind(PP.getSpelling(Tok));
95193326Sed  // Name of critical directive.
96193326Sed  DeclarationNameInfo DirName;
97193326Sed  StmtResult Directive = StmtError();
98193326Sed
99193326Sed  switch (DKind) {
100193326Sed  case OMPD_threadprivate:
101193326Sed    ConsumeToken();
102193326Sed    if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
103193326Sed      // The last seen token is annot_pragma_openmp_end - need to check for
104193326Sed      // extra tokens.
105193326Sed      if (Tok.isNot(tok::annot_pragma_openmp_end)) {
106193326Sed        Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
107193326Sed          << getOpenMPDirectiveName(OMPD_threadprivate);
108193326Sed        SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
109193326Sed      }
110193326Sed      DeclGroupPtrTy Res =
111193326Sed        Actions.ActOnOpenMPThreadprivateDirective(Loc,
112193326Sed                                                  Identifiers);
113193326Sed      Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
114193326Sed    }
115198092Srdivacky    SkipUntil(tok::annot_pragma_openmp_end);
116198893Srdivacky    break;
117193326Sed  case OMPD_parallel: {
118198092Srdivacky    ConsumeToken();
119193326Sed
120193326Sed    Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());
121193326Sed
122193326Sed    while (Tok.isNot(tok::annot_pragma_openmp_end)) {
123193326Sed      OpenMPClauseKind CKind = Tok.isAnnotation() ?
124193326Sed                                  OMPC_unknown :
125193326Sed                                  getOpenMPClauseKind(PP.getSpelling(Tok));
126193326Sed      OMPClause *Clause = ParseOpenMPClause(DKind, CKind,
127193326Sed                                            !FirstClauses[CKind].getInt());
128193326Sed      FirstClauses[CKind].setInt(true);
129193326Sed      if (Clause) {
130193326Sed        FirstClauses[CKind].setPointer(Clause);
131193326Sed        Clauses.push_back(Clause);
132212904Sdim      }
133193326Sed
134198092Srdivacky      // Skip ',' if any.
135193326Sed      if (Tok.is(tok::comma))
136193326Sed        ConsumeToken();
137226890Sdim    }
138198092Srdivacky    // End location of the directive.
139198092Srdivacky    EndLoc = Tok.getLocation();
140198092Srdivacky    // Consume final annot_pragma_openmp_end.
141198092Srdivacky    ConsumeToken();
142198092Srdivacky
143198092Srdivacky    StmtResult AssociatedStmt;
144212904Sdim    bool CreateDirective = true;
145198092Srdivacky    ParseScope OMPDirectiveScope(this, ScopeFlags);
146193326Sed    {
147193326Sed      // The body is a block scope like in Lambdas and Blocks.
148198092Srdivacky      Sema::CompoundScopeRAII CompoundScope(Actions);
149198092Srdivacky      Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1);
150193326Sed      Actions.ActOnStartOfCompoundStmt();
151193326Sed      // Parse statement
152198092Srdivacky      AssociatedStmt = ParseStatement();
153198092Srdivacky      Actions.ActOnFinishOfCompoundStmt();
154198092Srdivacky      if (!AssociatedStmt.isUsable()) {
155198092Srdivacky        Actions.ActOnCapturedRegionError();
156198893Srdivacky        CreateDirective = false;
157198893Srdivacky      } else {
158198092Srdivacky        AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take());
159193326Sed        CreateDirective = AssociatedStmt.isUsable();
160193326Sed      }
161193326Sed    }
162198092Srdivacky    if (CreateDirective)
163193326Sed      Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses,
164198893Srdivacky                                                         AssociatedStmt.take(),
165198893Srdivacky                                                         Loc, EndLoc);
166212904Sdim
167226890Sdim    // Exit scope.
168193326Sed    Actions.EndOpenMPDSABlock(Directive.get());
169193326Sed    OMPDirectiveScope.Exit();
170193326Sed    }
171193326Sed    break;
172193326Sed  case OMPD_unknown:
173193326Sed    Diag(Tok, diag::err_omp_unknown_directive);
174193326Sed    SkipUntil(tok::annot_pragma_openmp_end);
175193326Sed    break;
176193326Sed  case OMPD_task:
177193326Sed  case NUM_OPENMP_DIRECTIVES:
178193326Sed    Diag(Tok, diag::err_omp_unexpected_directive)
179193326Sed      << getOpenMPDirectiveName(DKind);
180193326Sed    SkipUntil(tok::annot_pragma_openmp_end);
181193326Sed    break;
182193326Sed  }
183193326Sed  return Directive;
184193326Sed}
185193326Sed
186193326Sed/// \brief Parses list of simple variables for '#pragma omp threadprivate'
187193326Sed/// directive.
188193326Sed///
189193326Sed///   simple-variable-list:
190212904Sdim///         '(' id-expression {, id-expression} ')'
191193326Sed///
192193326Sedbool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
193193326Sed                                      SmallVectorImpl<Expr *> &VarList,
194212904Sdim                                      bool AllowScopeSpecifier) {
195193326Sed  VarList.clear();
196226890Sdim  // Parse '('.
197226890Sdim  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
198193326Sed  if (T.expectAndConsume(diag::err_expected_lparen_after,
199193326Sed                         getOpenMPDirectiveName(Kind)))
200193326Sed    return true;
201198092Srdivacky  bool IsCorrect = true;
202198092Srdivacky  bool NoIdentIsFound = true;
203226890Sdim
204226890Sdim  // Read tokens while ')' or annot_pragma_openmp_end is not found.
205212904Sdim  while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
206198092Srdivacky    CXXScopeSpec SS;
207198092Srdivacky    SourceLocation TemplateKWLoc;
208221345Sdim    UnqualifiedId Name;
209218893Sdim    // Read var name.
210218893Sdim    Token PrevTok = Tok;
211218893Sdim    NoIdentIsFound = false;
212218893Sdim
213218893Sdim    if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
214218893Sdim        ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
215212904Sdim      IsCorrect = false;
216212904Sdim      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
217221345Sdim                StopBeforeMatch);
218199990Srdivacky    } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
219218893Sdim                                  TemplateKWLoc, Name)) {
220199990Srdivacky      IsCorrect = false;
221202379Srdivacky      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
222202379Srdivacky                StopBeforeMatch);
223193326Sed    } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
224193326Sed               Tok.isNot(tok::annot_pragma_openmp_end)) {
225193326Sed      IsCorrect = false;
226212904Sdim      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
227198893Srdivacky                StopBeforeMatch);
228198893Srdivacky      Diag(PrevTok.getLocation(), diag::err_expected_ident)
229193326Sed        << SourceRange(PrevTok.getLocation(), PrevTokLocation);
230193326Sed    } else {
231193326Sed      DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
232198893Srdivacky      ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
233193326Sed                                                       NameInfo);
234193326Sed      if (Res.isUsable())
235193326Sed        VarList.push_back(Res.take());
236193326Sed    }
237193326Sed    // Consume ','.
238193326Sed    if (Tok.is(tok::comma)) {
239193326Sed      ConsumeToken();
240212904Sdim    }
241193326Sed  }
242198092Srdivacky
243193326Sed  if (NoIdentIsFound) {
244193326Sed    Diag(Tok, diag::err_expected_ident);
245193326Sed    IsCorrect = false;
246212904Sdim  }
247212904Sdim
248193326Sed  // Parse ')'.
249193326Sed  IsCorrect = !T.consumeClose() && IsCorrect;
250193326Sed
251193326Sed  return !IsCorrect && VarList.empty();
252193326Sed}
253193326Sed
254193326Sed/// \brief Parsing of OpenMP clauses.
255193326Sed///
256193326Sed///    clause:
257198092Srdivacky///       default-clause|private-clause|firstprivate-clause|shared-clause
258218893Sdim///
259193326SedOMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
260193326Sed                                     OpenMPClauseKind CKind, bool FirstClause) {
261193326Sed  OMPClause *Clause = 0;
262193326Sed  bool ErrorFound = false;
263210299Sed  // Check if clause is allowed for the given directive.
264193326Sed  if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
265193326Sed    Diag(Tok, diag::err_omp_unexpected_clause)
266193326Sed      << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
267193326Sed    ErrorFound = true;
268193326Sed  }
269193326Sed
270193326Sed  switch (CKind) {
271193326Sed  case OMPC_default:
272193326Sed    // OpenMP [2.9.3.1, Restrictions]
273193326Sed    //  Only a single default clause may be specified on a parallel or task
274193326Sed    //  directive.
275193326Sed    if (!FirstClause) {
276212904Sdim      Diag(Tok, diag::err_omp_more_one_clause)
277193326Sed           << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
278195099Sed    }
279193326Sed
280193326Sed    Clause = ParseOpenMPSimpleClause(CKind);
281193326Sed    break;
282193326Sed  case OMPC_private:
283193326Sed  case OMPC_firstprivate:
284193326Sed  case OMPC_shared:
285193326Sed    Clause = ParseOpenMPVarListClause(CKind);
286212904Sdim    break;
287193326Sed  case OMPC_unknown:
288193326Sed    Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
289193326Sed      << getOpenMPDirectiveName(DKind);
290193326Sed    SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
291193326Sed    break;
292193326Sed  case OMPC_threadprivate:
293193326Sed  case NUM_OPENMP_CLAUSES:
294198092Srdivacky    Diag(Tok, diag::err_omp_unexpected_clause)
295193326Sed      << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
296198092Srdivacky    SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
297198092Srdivacky    break;
298193326Sed  }
299226890Sdim  return ErrorFound ? 0 : Clause;
300193326Sed}
301193326Sed
302193326Sed/// \brief Parsing of simple OpenMP clauses like 'default'.
303198092Srdivacky///
304193326Sed///    default-clause:
305198092Srdivacky///         'default' '(' 'none' | 'shared' ')
306193326Sed///
307193326SedOMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
308198092Srdivacky  SourceLocation Loc = Tok.getLocation();
309193326Sed  SourceLocation LOpen = ConsumeToken();
310193326Sed  // Parse '('.
311193326Sed  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
312198092Srdivacky  if (T.expectAndConsume(diag::err_expected_lparen_after,
313198092Srdivacky                         getOpenMPClauseName(Kind)))
314193326Sed    return 0;
315198092Srdivacky
316193326Sed  unsigned Type = Tok.isAnnotation() ?
317193326Sed                     unsigned(OMPC_DEFAULT_unknown) :
318193326Sed                     getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
319198092Srdivacky  SourceLocation TypeLoc = Tok.getLocation();
320193326Sed  if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
321193326Sed      Tok.isNot(tok::annot_pragma_openmp_end))
322193326Sed    ConsumeAnyToken();
323193326Sed
324193326Sed  // Parse ')'.
325198092Srdivacky  T.consumeClose();
326193326Sed
327193326Sed  return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
328193326Sed                                         Tok.getLocation());
329193326Sed}
330198092Srdivacky
331193326Sed/// \brief Parsing of OpenMP clause 'private', 'firstprivate',
332226890Sdim/// 'shared', 'copyin', or 'reduction'.
333198092Srdivacky///
334212904Sdim///    private-clause:
335193326Sed///       'private' '(' list ')'
336193326Sed///    firstprivate-clause:
337193326Sed///       'firstprivate' '(' list ')'
338193326Sed///    shared-clause:
339193326Sed///       'shared' '(' list ')'
340193326Sed///
341193326SedOMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
342198092Srdivacky  SourceLocation Loc = Tok.getLocation();
343193326Sed  SourceLocation LOpen = ConsumeToken();
344198092Srdivacky  // Parse '('.
345193326Sed  BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
346198092Srdivacky  if (T.expectAndConsume(diag::err_expected_lparen_after,
347193326Sed                         getOpenMPClauseName(Kind)))
348193326Sed    return 0;
349193326Sed
350193326Sed  SmallVector<Expr *, 5> Vars;
351193326Sed  bool IsComma = true;
352193326Sed  while (IsComma || (Tok.isNot(tok::r_paren) &&
353193326Sed                     Tok.isNot(tok::annot_pragma_openmp_end))) {
354193326Sed    // Parse variable
355218893Sdim    ExprResult VarExpr = ParseAssignmentExpression();
356193326Sed    if (VarExpr.isUsable()) {
357193326Sed      Vars.push_back(VarExpr.take());
358193326Sed    } else {
359193326Sed      SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
360193326Sed                StopBeforeMatch);
361193326Sed    }
362193326Sed    // Skip ',' if any
363199990Srdivacky    IsComma = Tok.is(tok::comma);
364199990Srdivacky    if (IsComma) {
365199990Srdivacky      ConsumeToken();
366210299Sed    } else if (Tok.isNot(tok::r_paren) &&
367210299Sed               Tok.isNot(tok::annot_pragma_openmp_end)) {
368210299Sed      Diag(Tok, diag::err_omp_expected_punc)
369210299Sed        << 1 << getOpenMPClauseName(Kind);
370210299Sed    }
371210299Sed  }
372210299Sed
373210299Sed  // Parse ')'.
374210299Sed  T.consumeClose();
375210299Sed  if (Vars.empty())
376210299Sed    return 0;
377210299Sed
378210299Sed  return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
379210299Sed                                          Tok.getLocation());
380210299Sed}
381210299Sed
382210299Sed