]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / clang / lib / Parse / ParseOpenMP.cpp
1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// \brief This file implements parsing of all OpenMP directives and clauses.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/AST/ASTConsumer.h"
15 #include "clang/AST/StmtOpenMP.h"
16 #include "clang/Parse/ParseDiagnostic.h"
17 #include "clang/Parse/Parser.h"
18 #include "clang/Sema/Scope.h"
19 #include "llvm/ADT/PointerIntPair.h"
20 #include "RAIIObjectsForParser.h"
21 using namespace clang;
22
23 //===----------------------------------------------------------------------===//
24 // OpenMP declarative directives.
25 //===----------------------------------------------------------------------===//
26
27 /// \brief Parsing of declarative OpenMP directives.
28 ///
29 ///       threadprivate-directive:
30 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
31 ///
32 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
33   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
34   ParenBraceBracketBalancer BalancerRAIIObj(*this);
35
36   SourceLocation Loc = ConsumeToken();
37   SmallVector<Expr *, 5> Identifiers;
38   OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
39                                   OMPD_unknown :
40                                   getOpenMPDirectiveKind(PP.getSpelling(Tok));
41
42   switch (DKind) {
43   case OMPD_threadprivate:
44     ConsumeToken();
45     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
46       // The last seen token is annot_pragma_openmp_end - need to check for
47       // extra tokens.
48       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
49         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
50           << getOpenMPDirectiveName(OMPD_threadprivate);
51         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
52       }
53       // Skip the last annot_pragma_openmp_end.
54       ConsumeToken();
55       return Actions.ActOnOpenMPThreadprivateDirective(Loc,
56                                                        Identifiers);
57     }
58     break;
59   case OMPD_unknown:
60     Diag(Tok, diag::err_omp_unknown_directive);
61     break;
62   case OMPD_parallel:
63   case OMPD_task:
64   case NUM_OPENMP_DIRECTIVES:
65     Diag(Tok, diag::err_omp_unexpected_directive)
66       << getOpenMPDirectiveName(DKind);
67     break;
68   }
69   SkipUntil(tok::annot_pragma_openmp_end);
70   return DeclGroupPtrTy();
71 }
72
73 /// \brief Parsing of declarative or executable OpenMP directives.
74 ///
75 ///       threadprivate-directive:
76 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
77 ///         annot_pragma_openmp_end
78 ///
79 ///       parallel-directive:
80 ///         annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end
81 ///
82 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
83   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
84   ParenBraceBracketBalancer BalancerRAIIObj(*this);
85   SmallVector<Expr *, 5> Identifiers;
86   SmallVector<OMPClause *, 5> Clauses;
87   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES>
88                                                FirstClauses(NUM_OPENMP_CLAUSES);
89   const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
90                               Scope::OpenMPDirectiveScope;
91   SourceLocation Loc = ConsumeToken(), EndLoc;
92   OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
93                                   OMPD_unknown :
94                                   getOpenMPDirectiveKind(PP.getSpelling(Tok));
95   // Name of critical directive.
96   DeclarationNameInfo DirName;
97   StmtResult Directive = StmtError();
98
99   switch (DKind) {
100   case OMPD_threadprivate:
101     ConsumeToken();
102     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
103       // The last seen token is annot_pragma_openmp_end - need to check for
104       // extra tokens.
105       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
106         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
107           << getOpenMPDirectiveName(OMPD_threadprivate);
108         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
109       }
110       DeclGroupPtrTy Res =
111         Actions.ActOnOpenMPThreadprivateDirective(Loc,
112                                                   Identifiers);
113       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
114     }
115     SkipUntil(tok::annot_pragma_openmp_end);
116     break;
117   case OMPD_parallel: {
118     ConsumeToken();
119
120     Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());
121
122     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
123       OpenMPClauseKind CKind = Tok.isAnnotation() ?
124                                   OMPC_unknown :
125                                   getOpenMPClauseKind(PP.getSpelling(Tok));
126       OMPClause *Clause = ParseOpenMPClause(DKind, CKind,
127                                             !FirstClauses[CKind].getInt());
128       FirstClauses[CKind].setInt(true);
129       if (Clause) {
130         FirstClauses[CKind].setPointer(Clause);
131         Clauses.push_back(Clause);
132       }
133
134       // Skip ',' if any.
135       if (Tok.is(tok::comma))
136         ConsumeToken();
137     }
138     // End location of the directive.
139     EndLoc = Tok.getLocation();
140     // Consume final annot_pragma_openmp_end.
141     ConsumeToken();
142
143     StmtResult AssociatedStmt;
144     bool CreateDirective = true;
145     ParseScope OMPDirectiveScope(this, ScopeFlags);
146     {
147       // The body is a block scope like in Lambdas and Blocks.
148       Sema::CompoundScopeRAII CompoundScope(Actions);
149       Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1);
150       Actions.ActOnStartOfCompoundStmt();
151       // Parse statement
152       AssociatedStmt = ParseStatement();
153       Actions.ActOnFinishOfCompoundStmt();
154       if (!AssociatedStmt.isUsable()) {
155         Actions.ActOnCapturedRegionError();
156         CreateDirective = false;
157       } else {
158         AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take());
159         CreateDirective = AssociatedStmt.isUsable();
160       }
161     }
162     if (CreateDirective)
163       Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses,
164                                                          AssociatedStmt.take(),
165                                                          Loc, EndLoc);
166
167     // Exit scope.
168     Actions.EndOpenMPDSABlock(Directive.get());
169     OMPDirectiveScope.Exit();
170     }
171     break;
172   case OMPD_unknown:
173     Diag(Tok, diag::err_omp_unknown_directive);
174     SkipUntil(tok::annot_pragma_openmp_end);
175     break;
176   case OMPD_task:
177   case NUM_OPENMP_DIRECTIVES:
178     Diag(Tok, diag::err_omp_unexpected_directive)
179       << getOpenMPDirectiveName(DKind);
180     SkipUntil(tok::annot_pragma_openmp_end);
181     break;
182   }
183   return Directive;
184 }
185
186 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
187 /// directive.
188 ///
189 ///   simple-variable-list:
190 ///         '(' id-expression {, id-expression} ')'
191 ///
192 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
193                                       SmallVectorImpl<Expr *> &VarList,
194                                       bool AllowScopeSpecifier) {
195   VarList.clear();
196   // Parse '('.
197   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
198   if (T.expectAndConsume(diag::err_expected_lparen_after,
199                          getOpenMPDirectiveName(Kind)))
200     return true;
201   bool IsCorrect = true;
202   bool NoIdentIsFound = true;
203
204   // Read tokens while ')' or annot_pragma_openmp_end is not found.
205   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
206     CXXScopeSpec SS;
207     SourceLocation TemplateKWLoc;
208     UnqualifiedId Name;
209     // Read var name.
210     Token PrevTok = Tok;
211     NoIdentIsFound = false;
212
213     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
214         ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
215       IsCorrect = false;
216       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
217                 StopBeforeMatch);
218     } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
219                                   TemplateKWLoc, Name)) {
220       IsCorrect = false;
221       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
222                 StopBeforeMatch);
223     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
224                Tok.isNot(tok::annot_pragma_openmp_end)) {
225       IsCorrect = false;
226       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
227                 StopBeforeMatch);
228       Diag(PrevTok.getLocation(), diag::err_expected_ident)
229         << SourceRange(PrevTok.getLocation(), PrevTokLocation);
230     } else {
231       DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
232       ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
233                                                        NameInfo);
234       if (Res.isUsable())
235         VarList.push_back(Res.take());
236     }
237     // Consume ','.
238     if (Tok.is(tok::comma)) {
239       ConsumeToken();
240     }
241   }
242
243   if (NoIdentIsFound) {
244     Diag(Tok, diag::err_expected_ident);
245     IsCorrect = false;
246   }
247
248   // Parse ')'.
249   IsCorrect = !T.consumeClose() && IsCorrect;
250
251   return !IsCorrect && VarList.empty();
252 }
253
254 /// \brief Parsing of OpenMP clauses.
255 ///
256 ///    clause:
257 ///       default-clause|private-clause|firstprivate-clause|shared-clause
258 ///
259 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
260                                      OpenMPClauseKind CKind, bool FirstClause) {
261   OMPClause *Clause = 0;
262   bool ErrorFound = false;
263   // Check if clause is allowed for the given directive.
264   if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
265     Diag(Tok, diag::err_omp_unexpected_clause)
266       << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
267     ErrorFound = true;
268   }
269
270   switch (CKind) {
271   case OMPC_default:
272     // OpenMP [2.9.3.1, Restrictions]
273     //  Only a single default clause may be specified on a parallel or task
274     //  directive.
275     if (!FirstClause) {
276       Diag(Tok, diag::err_omp_more_one_clause)
277            << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
278     }
279
280     Clause = ParseOpenMPSimpleClause(CKind);
281     break;
282   case OMPC_private:
283   case OMPC_firstprivate:
284   case OMPC_shared:
285     Clause = ParseOpenMPVarListClause(CKind);
286     break;
287   case OMPC_unknown:
288     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
289       << getOpenMPDirectiveName(DKind);
290     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
291     break;
292   case OMPC_threadprivate:
293   case NUM_OPENMP_CLAUSES:
294     Diag(Tok, diag::err_omp_unexpected_clause)
295       << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
296     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
297     break;
298   }
299   return ErrorFound ? 0 : Clause;
300 }
301
302 /// \brief Parsing of simple OpenMP clauses like 'default'.
303 ///
304 ///    default-clause:
305 ///         'default' '(' 'none' | 'shared' ')
306 ///
307 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
308   SourceLocation Loc = Tok.getLocation();
309   SourceLocation LOpen = ConsumeToken();
310   // Parse '('.
311   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
312   if (T.expectAndConsume(diag::err_expected_lparen_after,
313                          getOpenMPClauseName(Kind)))
314     return 0;
315
316   unsigned Type = Tok.isAnnotation() ?
317                      unsigned(OMPC_DEFAULT_unknown) :
318                      getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
319   SourceLocation TypeLoc = Tok.getLocation();
320   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
321       Tok.isNot(tok::annot_pragma_openmp_end))
322     ConsumeAnyToken();
323
324   // Parse ')'.
325   T.consumeClose();
326
327   return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
328                                          Tok.getLocation());
329 }
330
331 /// \brief Parsing of OpenMP clause 'private', 'firstprivate',
332 /// 'shared', 'copyin', or 'reduction'.
333 ///
334 ///    private-clause:
335 ///       'private' '(' list ')'
336 ///    firstprivate-clause:
337 ///       'firstprivate' '(' list ')'
338 ///    shared-clause:
339 ///       'shared' '(' list ')'
340 ///
341 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
342   SourceLocation Loc = Tok.getLocation();
343   SourceLocation LOpen = ConsumeToken();
344   // Parse '('.
345   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
346   if (T.expectAndConsume(diag::err_expected_lparen_after,
347                          getOpenMPClauseName(Kind)))
348     return 0;
349
350   SmallVector<Expr *, 5> Vars;
351   bool IsComma = true;
352   while (IsComma || (Tok.isNot(tok::r_paren) &&
353                      Tok.isNot(tok::annot_pragma_openmp_end))) {
354     // Parse variable
355     ExprResult VarExpr = ParseAssignmentExpression();
356     if (VarExpr.isUsable()) {
357       Vars.push_back(VarExpr.take());
358     } else {
359       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
360                 StopBeforeMatch);
361     }
362     // Skip ',' if any
363     IsComma = Tok.is(tok::comma);
364     if (IsComma) {
365       ConsumeToken();
366     } else if (Tok.isNot(tok::r_paren) &&
367                Tok.isNot(tok::annot_pragma_openmp_end)) {
368       Diag(Tok, diag::err_omp_expected_punc)
369         << 1 << getOpenMPClauseName(Kind);
370     }
371   }
372
373   // Parse ')'.
374   T.consumeClose();
375   if (Vars.empty())
376     return 0;
377
378   return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
379                                           Tok.getLocation());
380 }
381