1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \brief This file implements parsing of all OpenMP directives and clauses.
12 //===----------------------------------------------------------------------===//
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;
23 //===----------------------------------------------------------------------===//
24 // OpenMP declarative directives.
25 //===----------------------------------------------------------------------===//
27 /// \brief Parsing of declarative OpenMP directives.
29 /// threadprivate-directive:
30 /// annot_pragma_openmp 'threadprivate' simple-variable-list
32 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
33 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
34 ParenBraceBracketBalancer BalancerRAIIObj(*this);
36 SourceLocation Loc = ConsumeToken();
37 SmallVector<Expr *, 5> Identifiers;
38 OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
40 getOpenMPDirectiveKind(PP.getSpelling(Tok));
43 case OMPD_threadprivate:
45 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
46 // The last seen token is annot_pragma_openmp_end - need to check for
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);
53 // Skip the last annot_pragma_openmp_end.
55 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
60 Diag(Tok, diag::err_omp_unknown_directive);
64 case NUM_OPENMP_DIRECTIVES:
65 Diag(Tok, diag::err_omp_unexpected_directive)
66 << getOpenMPDirectiveName(DKind);
69 SkipUntil(tok::annot_pragma_openmp_end);
70 return DeclGroupPtrTy();
73 /// \brief Parsing of declarative or executable OpenMP directives.
75 /// threadprivate-directive:
76 /// annot_pragma_openmp 'threadprivate' simple-variable-list
77 /// annot_pragma_openmp_end
79 /// parallel-directive:
80 /// annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end
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() ?
94 getOpenMPDirectiveKind(PP.getSpelling(Tok));
95 // Name of critical directive.
96 DeclarationNameInfo DirName;
97 StmtResult Directive = StmtError();
100 case OMPD_threadprivate:
102 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
103 // The last seen token is annot_pragma_openmp_end - need to check for
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);
111 Actions.ActOnOpenMPThreadprivateDirective(Loc,
113 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
115 SkipUntil(tok::annot_pragma_openmp_end);
117 case OMPD_parallel: {
120 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());
122 while (Tok.isNot(tok::annot_pragma_openmp_end)) {
123 OpenMPClauseKind CKind = Tok.isAnnotation() ?
125 getOpenMPClauseKind(PP.getSpelling(Tok));
126 OMPClause *Clause = ParseOpenMPClause(DKind, CKind,
127 !FirstClauses[CKind].getInt());
128 FirstClauses[CKind].setInt(true);
130 FirstClauses[CKind].setPointer(Clause);
131 Clauses.push_back(Clause);
135 if (Tok.is(tok::comma))
138 // End location of the directive.
139 EndLoc = Tok.getLocation();
140 // Consume final annot_pragma_openmp_end.
143 StmtResult AssociatedStmt;
144 bool CreateDirective = true;
145 ParseScope OMPDirectiveScope(this, ScopeFlags);
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();
152 AssociatedStmt = ParseStatement();
153 Actions.ActOnFinishOfCompoundStmt();
154 if (!AssociatedStmt.isUsable()) {
155 Actions.ActOnCapturedRegionError();
156 CreateDirective = false;
158 AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take());
159 CreateDirective = AssociatedStmt.isUsable();
163 Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses,
164 AssociatedStmt.take(),
168 Actions.EndOpenMPDSABlock(Directive.get());
169 OMPDirectiveScope.Exit();
173 Diag(Tok, diag::err_omp_unknown_directive);
174 SkipUntil(tok::annot_pragma_openmp_end);
177 case NUM_OPENMP_DIRECTIVES:
178 Diag(Tok, diag::err_omp_unexpected_directive)
179 << getOpenMPDirectiveName(DKind);
180 SkipUntil(tok::annot_pragma_openmp_end);
186 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
189 /// simple-variable-list:
190 /// '(' id-expression {, id-expression} ')'
192 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
193 SmallVectorImpl<Expr *> &VarList,
194 bool AllowScopeSpecifier) {
197 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
198 if (T.expectAndConsume(diag::err_expected_lparen_after,
199 getOpenMPDirectiveName(Kind)))
201 bool IsCorrect = true;
202 bool NoIdentIsFound = true;
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)) {
207 SourceLocation TemplateKWLoc;
211 NoIdentIsFound = false;
213 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
214 ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
216 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
218 } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
219 TemplateKWLoc, Name)) {
221 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
223 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
224 Tok.isNot(tok::annot_pragma_openmp_end)) {
226 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
228 Diag(PrevTok.getLocation(), diag::err_expected_ident)
229 << SourceRange(PrevTok.getLocation(), PrevTokLocation);
231 DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
232 ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS,
235 VarList.push_back(Res.take());
238 if (Tok.is(tok::comma)) {
243 if (NoIdentIsFound) {
244 Diag(Tok, diag::err_expected_ident);
249 IsCorrect = !T.consumeClose() && IsCorrect;
251 return !IsCorrect && VarList.empty();
254 /// \brief Parsing of OpenMP clauses.
257 /// default-clause|private-clause|firstprivate-clause|shared-clause
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);
272 // OpenMP [2.9.3.1, Restrictions]
273 // Only a single default clause may be specified on a parallel or task
276 Diag(Tok, diag::err_omp_more_one_clause)
277 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
280 Clause = ParseOpenMPSimpleClause(CKind);
283 case OMPC_firstprivate:
285 Clause = ParseOpenMPVarListClause(CKind);
288 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
289 << getOpenMPDirectiveName(DKind);
290 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
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);
299 return ErrorFound ? 0 : Clause;
302 /// \brief Parsing of simple OpenMP clauses like 'default'.
305 /// 'default' '(' 'none' | 'shared' ')
307 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
308 SourceLocation Loc = Tok.getLocation();
309 SourceLocation LOpen = ConsumeToken();
311 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
312 if (T.expectAndConsume(diag::err_expected_lparen_after,
313 getOpenMPClauseName(Kind)))
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))
327 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
331 /// \brief Parsing of OpenMP clause 'private', 'firstprivate',
332 /// 'shared', 'copyin', or 'reduction'.
335 /// 'private' '(' list ')'
336 /// firstprivate-clause:
337 /// 'firstprivate' '(' list ')'
339 /// 'shared' '(' list ')'
341 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
342 SourceLocation Loc = Tok.getLocation();
343 SourceLocation LOpen = ConsumeToken();
345 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
346 if (T.expectAndConsume(diag::err_expected_lparen_after,
347 getOpenMPClauseName(Kind)))
350 SmallVector<Expr *, 5> Vars;
352 while (IsComma || (Tok.isNot(tok::r_paren) &&
353 Tok.isNot(tok::annot_pragma_openmp_end))) {
355 ExprResult VarExpr = ParseAssignmentExpression();
356 if (VarExpr.isUsable()) {
357 Vars.push_back(VarExpr.take());
359 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
363 IsComma = Tok.is(tok::comma);
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);
378 return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,