1f4a2713aSLionel Sambuc //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc /// \file
10f4a2713aSLionel Sambuc /// \brief This file implements parsing of all OpenMP directives and clauses.
11f4a2713aSLionel Sambuc ///
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14*0a6a1f1dSLionel Sambuc #include "RAIIObjectsForParser.h"
15f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h"
16*0a6a1f1dSLionel Sambuc #include "clang/AST/ASTContext.h"
17f4a2713aSLionel Sambuc #include "clang/AST/StmtOpenMP.h"
18f4a2713aSLionel Sambuc #include "clang/Parse/ParseDiagnostic.h"
19f4a2713aSLionel Sambuc #include "clang/Parse/Parser.h"
20f4a2713aSLionel Sambuc #include "clang/Sema/Scope.h"
21f4a2713aSLionel Sambuc #include "llvm/ADT/PointerIntPair.h"
22f4a2713aSLionel Sambuc using namespace clang;
23f4a2713aSLionel Sambuc
24f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
25f4a2713aSLionel Sambuc // OpenMP declarative directives.
26f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
27f4a2713aSLionel Sambuc
ParseOpenMPDirectiveKind(Parser & P)28*0a6a1f1dSLionel Sambuc static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
29*0a6a1f1dSLionel Sambuc // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
30*0a6a1f1dSLionel Sambuc // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
31*0a6a1f1dSLionel Sambuc // TODO: add other combined directives in topological order.
32*0a6a1f1dSLionel Sambuc const OpenMPDirectiveKind F[][3] = {
33*0a6a1f1dSLionel Sambuc { OMPD_for, OMPD_simd, OMPD_for_simd },
34*0a6a1f1dSLionel Sambuc { OMPD_parallel, OMPD_for, OMPD_parallel_for },
35*0a6a1f1dSLionel Sambuc { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
36*0a6a1f1dSLionel Sambuc { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }
37*0a6a1f1dSLionel Sambuc };
38*0a6a1f1dSLionel Sambuc auto Tok = P.getCurToken();
39*0a6a1f1dSLionel Sambuc auto DKind =
40*0a6a1f1dSLionel Sambuc Tok.isAnnotation()
41*0a6a1f1dSLionel Sambuc ? OMPD_unknown
42*0a6a1f1dSLionel Sambuc : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
43*0a6a1f1dSLionel Sambuc for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
44*0a6a1f1dSLionel Sambuc if (DKind == F[i][0]) {
45*0a6a1f1dSLionel Sambuc Tok = P.getPreprocessor().LookAhead(0);
46*0a6a1f1dSLionel Sambuc auto SDKind =
47*0a6a1f1dSLionel Sambuc Tok.isAnnotation()
48*0a6a1f1dSLionel Sambuc ? OMPD_unknown
49*0a6a1f1dSLionel Sambuc : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
50*0a6a1f1dSLionel Sambuc if (SDKind == F[i][1]) {
51*0a6a1f1dSLionel Sambuc P.ConsumeToken();
52*0a6a1f1dSLionel Sambuc DKind = F[i][2];
53*0a6a1f1dSLionel Sambuc }
54*0a6a1f1dSLionel Sambuc }
55*0a6a1f1dSLionel Sambuc }
56*0a6a1f1dSLionel Sambuc return DKind;
57*0a6a1f1dSLionel Sambuc }
58*0a6a1f1dSLionel Sambuc
59f4a2713aSLionel Sambuc /// \brief Parsing of declarative OpenMP directives.
60f4a2713aSLionel Sambuc ///
61f4a2713aSLionel Sambuc /// threadprivate-directive:
62f4a2713aSLionel Sambuc /// annot_pragma_openmp 'threadprivate' simple-variable-list
63f4a2713aSLionel Sambuc ///
ParseOpenMPDeclarativeDirective()64f4a2713aSLionel Sambuc Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
65f4a2713aSLionel Sambuc assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
66f4a2713aSLionel Sambuc ParenBraceBracketBalancer BalancerRAIIObj(*this);
67f4a2713aSLionel Sambuc
68f4a2713aSLionel Sambuc SourceLocation Loc = ConsumeToken();
69f4a2713aSLionel Sambuc SmallVector<Expr *, 5> Identifiers;
70*0a6a1f1dSLionel Sambuc auto DKind = ParseOpenMPDirectiveKind(*this);
71f4a2713aSLionel Sambuc
72f4a2713aSLionel Sambuc switch (DKind) {
73f4a2713aSLionel Sambuc case OMPD_threadprivate:
74f4a2713aSLionel Sambuc ConsumeToken();
75f4a2713aSLionel Sambuc if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
76f4a2713aSLionel Sambuc // The last seen token is annot_pragma_openmp_end - need to check for
77f4a2713aSLionel Sambuc // extra tokens.
78f4a2713aSLionel Sambuc if (Tok.isNot(tok::annot_pragma_openmp_end)) {
79f4a2713aSLionel Sambuc Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
80f4a2713aSLionel Sambuc << getOpenMPDirectiveName(OMPD_threadprivate);
81f4a2713aSLionel Sambuc SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
82f4a2713aSLionel Sambuc }
83f4a2713aSLionel Sambuc // Skip the last annot_pragma_openmp_end.
84f4a2713aSLionel Sambuc ConsumeToken();
85*0a6a1f1dSLionel Sambuc return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
86f4a2713aSLionel Sambuc }
87f4a2713aSLionel Sambuc break;
88f4a2713aSLionel Sambuc case OMPD_unknown:
89f4a2713aSLionel Sambuc Diag(Tok, diag::err_omp_unknown_directive);
90f4a2713aSLionel Sambuc break;
91f4a2713aSLionel Sambuc case OMPD_parallel:
92*0a6a1f1dSLionel Sambuc case OMPD_simd:
93f4a2713aSLionel Sambuc case OMPD_task:
94*0a6a1f1dSLionel Sambuc case OMPD_taskyield:
95*0a6a1f1dSLionel Sambuc case OMPD_barrier:
96*0a6a1f1dSLionel Sambuc case OMPD_taskwait:
97*0a6a1f1dSLionel Sambuc case OMPD_flush:
98*0a6a1f1dSLionel Sambuc case OMPD_for:
99*0a6a1f1dSLionel Sambuc case OMPD_for_simd:
100*0a6a1f1dSLionel Sambuc case OMPD_sections:
101*0a6a1f1dSLionel Sambuc case OMPD_section:
102*0a6a1f1dSLionel Sambuc case OMPD_single:
103*0a6a1f1dSLionel Sambuc case OMPD_master:
104*0a6a1f1dSLionel Sambuc case OMPD_ordered:
105*0a6a1f1dSLionel Sambuc case OMPD_critical:
106*0a6a1f1dSLionel Sambuc case OMPD_parallel_for:
107*0a6a1f1dSLionel Sambuc case OMPD_parallel_for_simd:
108*0a6a1f1dSLionel Sambuc case OMPD_parallel_sections:
109*0a6a1f1dSLionel Sambuc case OMPD_atomic:
110*0a6a1f1dSLionel Sambuc case OMPD_target:
111*0a6a1f1dSLionel Sambuc case OMPD_teams:
112f4a2713aSLionel Sambuc Diag(Tok, diag::err_omp_unexpected_directive)
113f4a2713aSLionel Sambuc << getOpenMPDirectiveName(DKind);
114f4a2713aSLionel Sambuc break;
115f4a2713aSLionel Sambuc }
116f4a2713aSLionel Sambuc SkipUntil(tok::annot_pragma_openmp_end);
117f4a2713aSLionel Sambuc return DeclGroupPtrTy();
118f4a2713aSLionel Sambuc }
119f4a2713aSLionel Sambuc
120f4a2713aSLionel Sambuc /// \brief Parsing of declarative or executable OpenMP directives.
121f4a2713aSLionel Sambuc ///
122f4a2713aSLionel Sambuc /// threadprivate-directive:
123f4a2713aSLionel Sambuc /// annot_pragma_openmp 'threadprivate' simple-variable-list
124f4a2713aSLionel Sambuc /// annot_pragma_openmp_end
125f4a2713aSLionel Sambuc ///
126*0a6a1f1dSLionel Sambuc /// executable-directive:
127*0a6a1f1dSLionel Sambuc /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
128*0a6a1f1dSLionel Sambuc /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
129*0a6a1f1dSLionel Sambuc /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
130*0a6a1f1dSLionel Sambuc /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
131*0a6a1f1dSLionel Sambuc /// 'for simd' | 'parallel for simd' | 'target' | 'teams' {clause}
132*0a6a1f1dSLionel Sambuc /// annot_pragma_openmp_end
133f4a2713aSLionel Sambuc ///
134*0a6a1f1dSLionel Sambuc StmtResult
ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed)135*0a6a1f1dSLionel Sambuc Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
136f4a2713aSLionel Sambuc assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
137f4a2713aSLionel Sambuc ParenBraceBracketBalancer BalancerRAIIObj(*this);
138f4a2713aSLionel Sambuc SmallVector<Expr *, 5> Identifiers;
139f4a2713aSLionel Sambuc SmallVector<OMPClause *, 5> Clauses;
140*0a6a1f1dSLionel Sambuc SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
141*0a6a1f1dSLionel Sambuc FirstClauses(OMPC_unknown + 1);
142*0a6a1f1dSLionel Sambuc unsigned ScopeFlags =
143*0a6a1f1dSLionel Sambuc Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
144f4a2713aSLionel Sambuc SourceLocation Loc = ConsumeToken(), EndLoc;
145*0a6a1f1dSLionel Sambuc auto DKind = ParseOpenMPDirectiveKind(*this);
146f4a2713aSLionel Sambuc // Name of critical directive.
147f4a2713aSLionel Sambuc DeclarationNameInfo DirName;
148f4a2713aSLionel Sambuc StmtResult Directive = StmtError();
149*0a6a1f1dSLionel Sambuc bool HasAssociatedStatement = true;
150*0a6a1f1dSLionel Sambuc bool FlushHasClause = false;
151f4a2713aSLionel Sambuc
152f4a2713aSLionel Sambuc switch (DKind) {
153f4a2713aSLionel Sambuc case OMPD_threadprivate:
154f4a2713aSLionel Sambuc ConsumeToken();
155f4a2713aSLionel Sambuc if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
156f4a2713aSLionel Sambuc // The last seen token is annot_pragma_openmp_end - need to check for
157f4a2713aSLionel Sambuc // extra tokens.
158f4a2713aSLionel Sambuc if (Tok.isNot(tok::annot_pragma_openmp_end)) {
159f4a2713aSLionel Sambuc Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
160f4a2713aSLionel Sambuc << getOpenMPDirectiveName(OMPD_threadprivate);
161f4a2713aSLionel Sambuc SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
162f4a2713aSLionel Sambuc }
163f4a2713aSLionel Sambuc DeclGroupPtrTy Res =
164*0a6a1f1dSLionel Sambuc Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
165f4a2713aSLionel Sambuc Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
166f4a2713aSLionel Sambuc }
167f4a2713aSLionel Sambuc SkipUntil(tok::annot_pragma_openmp_end);
168f4a2713aSLionel Sambuc break;
169*0a6a1f1dSLionel Sambuc case OMPD_flush:
170*0a6a1f1dSLionel Sambuc if (PP.LookAhead(0).is(tok::l_paren)) {
171*0a6a1f1dSLionel Sambuc FlushHasClause = true;
172*0a6a1f1dSLionel Sambuc // Push copy of the current token back to stream to properly parse
173*0a6a1f1dSLionel Sambuc // pseudo-clause OMPFlushClause.
174*0a6a1f1dSLionel Sambuc PP.EnterToken(Tok);
175*0a6a1f1dSLionel Sambuc }
176*0a6a1f1dSLionel Sambuc case OMPD_taskyield:
177*0a6a1f1dSLionel Sambuc case OMPD_barrier:
178*0a6a1f1dSLionel Sambuc case OMPD_taskwait:
179*0a6a1f1dSLionel Sambuc if (!StandAloneAllowed) {
180*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_omp_immediate_directive)
181*0a6a1f1dSLionel Sambuc << getOpenMPDirectiveName(DKind);
182*0a6a1f1dSLionel Sambuc }
183*0a6a1f1dSLionel Sambuc HasAssociatedStatement = false;
184*0a6a1f1dSLionel Sambuc // Fall through for further analysis.
185*0a6a1f1dSLionel Sambuc case OMPD_parallel:
186*0a6a1f1dSLionel Sambuc case OMPD_simd:
187*0a6a1f1dSLionel Sambuc case OMPD_for:
188*0a6a1f1dSLionel Sambuc case OMPD_for_simd:
189*0a6a1f1dSLionel Sambuc case OMPD_sections:
190*0a6a1f1dSLionel Sambuc case OMPD_single:
191*0a6a1f1dSLionel Sambuc case OMPD_section:
192*0a6a1f1dSLionel Sambuc case OMPD_master:
193*0a6a1f1dSLionel Sambuc case OMPD_critical:
194*0a6a1f1dSLionel Sambuc case OMPD_parallel_for:
195*0a6a1f1dSLionel Sambuc case OMPD_parallel_for_simd:
196*0a6a1f1dSLionel Sambuc case OMPD_parallel_sections:
197*0a6a1f1dSLionel Sambuc case OMPD_task:
198*0a6a1f1dSLionel Sambuc case OMPD_ordered:
199*0a6a1f1dSLionel Sambuc case OMPD_atomic:
200*0a6a1f1dSLionel Sambuc case OMPD_target:
201*0a6a1f1dSLionel Sambuc case OMPD_teams: {
202f4a2713aSLionel Sambuc ConsumeToken();
203*0a6a1f1dSLionel Sambuc // Parse directive name of the 'critical' directive if any.
204*0a6a1f1dSLionel Sambuc if (DKind == OMPD_critical) {
205*0a6a1f1dSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren,
206*0a6a1f1dSLionel Sambuc tok::annot_pragma_openmp_end);
207*0a6a1f1dSLionel Sambuc if (!T.consumeOpen()) {
208*0a6a1f1dSLionel Sambuc if (Tok.isAnyIdentifier()) {
209*0a6a1f1dSLionel Sambuc DirName =
210*0a6a1f1dSLionel Sambuc DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
211*0a6a1f1dSLionel Sambuc ConsumeAnyToken();
212*0a6a1f1dSLionel Sambuc } else {
213*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_omp_expected_identifier_for_critical);
214*0a6a1f1dSLionel Sambuc }
215*0a6a1f1dSLionel Sambuc T.consumeClose();
216*0a6a1f1dSLionel Sambuc }
217*0a6a1f1dSLionel Sambuc }
218f4a2713aSLionel Sambuc
219*0a6a1f1dSLionel Sambuc if (isOpenMPLoopDirective(DKind))
220*0a6a1f1dSLionel Sambuc ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
221*0a6a1f1dSLionel Sambuc if (isOpenMPSimdDirective(DKind))
222*0a6a1f1dSLionel Sambuc ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
223*0a6a1f1dSLionel Sambuc ParseScope OMPDirectiveScope(this, ScopeFlags);
224*0a6a1f1dSLionel Sambuc Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
225f4a2713aSLionel Sambuc
226f4a2713aSLionel Sambuc while (Tok.isNot(tok::annot_pragma_openmp_end)) {
227*0a6a1f1dSLionel Sambuc OpenMPClauseKind CKind =
228*0a6a1f1dSLionel Sambuc Tok.isAnnotation()
229*0a6a1f1dSLionel Sambuc ? OMPC_unknown
230*0a6a1f1dSLionel Sambuc : FlushHasClause ? OMPC_flush
231*0a6a1f1dSLionel Sambuc : getOpenMPClauseKind(PP.getSpelling(Tok));
232*0a6a1f1dSLionel Sambuc FlushHasClause = false;
233*0a6a1f1dSLionel Sambuc OMPClause *Clause =
234*0a6a1f1dSLionel Sambuc ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
235f4a2713aSLionel Sambuc FirstClauses[CKind].setInt(true);
236f4a2713aSLionel Sambuc if (Clause) {
237f4a2713aSLionel Sambuc FirstClauses[CKind].setPointer(Clause);
238f4a2713aSLionel Sambuc Clauses.push_back(Clause);
239f4a2713aSLionel Sambuc }
240f4a2713aSLionel Sambuc
241f4a2713aSLionel Sambuc // Skip ',' if any.
242f4a2713aSLionel Sambuc if (Tok.is(tok::comma))
243f4a2713aSLionel Sambuc ConsumeToken();
244f4a2713aSLionel Sambuc }
245f4a2713aSLionel Sambuc // End location of the directive.
246f4a2713aSLionel Sambuc EndLoc = Tok.getLocation();
247f4a2713aSLionel Sambuc // Consume final annot_pragma_openmp_end.
248f4a2713aSLionel Sambuc ConsumeToken();
249f4a2713aSLionel Sambuc
250f4a2713aSLionel Sambuc StmtResult AssociatedStmt;
251f4a2713aSLionel Sambuc bool CreateDirective = true;
252*0a6a1f1dSLionel Sambuc if (HasAssociatedStatement) {
253f4a2713aSLionel Sambuc // The body is a block scope like in Lambdas and Blocks.
254f4a2713aSLionel Sambuc Sema::CompoundScopeRAII CompoundScope(Actions);
255*0a6a1f1dSLionel Sambuc Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
256f4a2713aSLionel Sambuc Actions.ActOnStartOfCompoundStmt();
257f4a2713aSLionel Sambuc // Parse statement
258f4a2713aSLionel Sambuc AssociatedStmt = ParseStatement();
259f4a2713aSLionel Sambuc Actions.ActOnFinishOfCompoundStmt();
260f4a2713aSLionel Sambuc if (!AssociatedStmt.isUsable()) {
261f4a2713aSLionel Sambuc Actions.ActOnCapturedRegionError();
262f4a2713aSLionel Sambuc CreateDirective = false;
263f4a2713aSLionel Sambuc } else {
264*0a6a1f1dSLionel Sambuc AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
265f4a2713aSLionel Sambuc CreateDirective = AssociatedStmt.isUsable();
266f4a2713aSLionel Sambuc }
267f4a2713aSLionel Sambuc }
268f4a2713aSLionel Sambuc if (CreateDirective)
269*0a6a1f1dSLionel Sambuc Directive = Actions.ActOnOpenMPExecutableDirective(
270*0a6a1f1dSLionel Sambuc DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
271f4a2713aSLionel Sambuc
272f4a2713aSLionel Sambuc // Exit scope.
273f4a2713aSLionel Sambuc Actions.EndOpenMPDSABlock(Directive.get());
274f4a2713aSLionel Sambuc OMPDirectiveScope.Exit();
275f4a2713aSLionel Sambuc break;
276*0a6a1f1dSLionel Sambuc }
277f4a2713aSLionel Sambuc case OMPD_unknown:
278f4a2713aSLionel Sambuc Diag(Tok, diag::err_omp_unknown_directive);
279f4a2713aSLionel Sambuc SkipUntil(tok::annot_pragma_openmp_end);
280f4a2713aSLionel Sambuc break;
281f4a2713aSLionel Sambuc }
282f4a2713aSLionel Sambuc return Directive;
283f4a2713aSLionel Sambuc }
284f4a2713aSLionel Sambuc
285f4a2713aSLionel Sambuc /// \brief Parses list of simple variables for '#pragma omp threadprivate'
286f4a2713aSLionel Sambuc /// directive.
287f4a2713aSLionel Sambuc ///
288f4a2713aSLionel Sambuc /// simple-variable-list:
289f4a2713aSLionel Sambuc /// '(' id-expression {, id-expression} ')'
290f4a2713aSLionel Sambuc ///
ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,SmallVectorImpl<Expr * > & VarList,bool AllowScopeSpecifier)291f4a2713aSLionel Sambuc bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
292f4a2713aSLionel Sambuc SmallVectorImpl<Expr *> &VarList,
293f4a2713aSLionel Sambuc bool AllowScopeSpecifier) {
294f4a2713aSLionel Sambuc VarList.clear();
295f4a2713aSLionel Sambuc // Parse '('.
296f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
297f4a2713aSLionel Sambuc if (T.expectAndConsume(diag::err_expected_lparen_after,
298f4a2713aSLionel Sambuc getOpenMPDirectiveName(Kind)))
299f4a2713aSLionel Sambuc return true;
300f4a2713aSLionel Sambuc bool IsCorrect = true;
301f4a2713aSLionel Sambuc bool NoIdentIsFound = true;
302f4a2713aSLionel Sambuc
303f4a2713aSLionel Sambuc // Read tokens while ')' or annot_pragma_openmp_end is not found.
304f4a2713aSLionel Sambuc while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
305f4a2713aSLionel Sambuc CXXScopeSpec SS;
306f4a2713aSLionel Sambuc SourceLocation TemplateKWLoc;
307f4a2713aSLionel Sambuc UnqualifiedId Name;
308f4a2713aSLionel Sambuc // Read var name.
309f4a2713aSLionel Sambuc Token PrevTok = Tok;
310f4a2713aSLionel Sambuc NoIdentIsFound = false;
311f4a2713aSLionel Sambuc
312f4a2713aSLionel Sambuc if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
313f4a2713aSLionel Sambuc ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
314f4a2713aSLionel Sambuc IsCorrect = false;
315f4a2713aSLionel Sambuc SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
316f4a2713aSLionel Sambuc StopBeforeMatch);
317f4a2713aSLionel Sambuc } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
318f4a2713aSLionel Sambuc TemplateKWLoc, Name)) {
319f4a2713aSLionel Sambuc IsCorrect = false;
320f4a2713aSLionel Sambuc SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
321f4a2713aSLionel Sambuc StopBeforeMatch);
322f4a2713aSLionel Sambuc } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
323f4a2713aSLionel Sambuc Tok.isNot(tok::annot_pragma_openmp_end)) {
324f4a2713aSLionel Sambuc IsCorrect = false;
325f4a2713aSLionel Sambuc SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
326f4a2713aSLionel Sambuc StopBeforeMatch);
327*0a6a1f1dSLionel Sambuc Diag(PrevTok.getLocation(), diag::err_expected)
328*0a6a1f1dSLionel Sambuc << tok::identifier
329f4a2713aSLionel Sambuc << SourceRange(PrevTok.getLocation(), PrevTokLocation);
330f4a2713aSLionel Sambuc } else {
331f4a2713aSLionel Sambuc DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
332*0a6a1f1dSLionel Sambuc ExprResult Res =
333*0a6a1f1dSLionel Sambuc Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
334f4a2713aSLionel Sambuc if (Res.isUsable())
335*0a6a1f1dSLionel Sambuc VarList.push_back(Res.get());
336f4a2713aSLionel Sambuc }
337f4a2713aSLionel Sambuc // Consume ','.
338f4a2713aSLionel Sambuc if (Tok.is(tok::comma)) {
339f4a2713aSLionel Sambuc ConsumeToken();
340f4a2713aSLionel Sambuc }
341f4a2713aSLionel Sambuc }
342f4a2713aSLionel Sambuc
343f4a2713aSLionel Sambuc if (NoIdentIsFound) {
344*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_expected) << tok::identifier;
345f4a2713aSLionel Sambuc IsCorrect = false;
346f4a2713aSLionel Sambuc }
347f4a2713aSLionel Sambuc
348f4a2713aSLionel Sambuc // Parse ')'.
349f4a2713aSLionel Sambuc IsCorrect = !T.consumeClose() && IsCorrect;
350f4a2713aSLionel Sambuc
351f4a2713aSLionel Sambuc return !IsCorrect && VarList.empty();
352f4a2713aSLionel Sambuc }
353f4a2713aSLionel Sambuc
354f4a2713aSLionel Sambuc /// \brief Parsing of OpenMP clauses.
355f4a2713aSLionel Sambuc ///
356f4a2713aSLionel Sambuc /// clause:
357*0a6a1f1dSLionel Sambuc /// if-clause | final-clause | num_threads-clause | safelen-clause |
358f4a2713aSLionel Sambuc /// default-clause | private-clause | firstprivate-clause | shared-clause
359*0a6a1f1dSLionel Sambuc /// | linear-clause | aligned-clause | collapse-clause |
360*0a6a1f1dSLionel Sambuc /// lastprivate-clause | reduction-clause | proc_bind-clause |
361*0a6a1f1dSLionel Sambuc /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
362*0a6a1f1dSLionel Sambuc /// mergeable-clause | flush-clause | read-clause | write-clause |
363*0a6a1f1dSLionel Sambuc /// update-clause | capture-clause | seq_cst-clause
364f4a2713aSLionel Sambuc ///
ParseOpenMPClause(OpenMPDirectiveKind DKind,OpenMPClauseKind CKind,bool FirstClause)365f4a2713aSLionel Sambuc OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
366f4a2713aSLionel Sambuc OpenMPClauseKind CKind, bool FirstClause) {
367*0a6a1f1dSLionel Sambuc OMPClause *Clause = nullptr;
368f4a2713aSLionel Sambuc bool ErrorFound = false;
369f4a2713aSLionel Sambuc // Check if clause is allowed for the given directive.
370f4a2713aSLionel Sambuc if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
371*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
372*0a6a1f1dSLionel Sambuc << getOpenMPDirectiveName(DKind);
373f4a2713aSLionel Sambuc ErrorFound = true;
374f4a2713aSLionel Sambuc }
375f4a2713aSLionel Sambuc
376f4a2713aSLionel Sambuc switch (CKind) {
377*0a6a1f1dSLionel Sambuc case OMPC_if:
378*0a6a1f1dSLionel Sambuc case OMPC_final:
379*0a6a1f1dSLionel Sambuc case OMPC_num_threads:
380*0a6a1f1dSLionel Sambuc case OMPC_safelen:
381*0a6a1f1dSLionel Sambuc case OMPC_collapse:
382*0a6a1f1dSLionel Sambuc // OpenMP [2.5, Restrictions]
383*0a6a1f1dSLionel Sambuc // At most one if clause can appear on the directive.
384*0a6a1f1dSLionel Sambuc // At most one num_threads clause can appear on the directive.
385*0a6a1f1dSLionel Sambuc // OpenMP [2.8.1, simd construct, Restrictions]
386*0a6a1f1dSLionel Sambuc // Only one safelen clause can appear on a simd directive.
387*0a6a1f1dSLionel Sambuc // Only one collapse clause can appear on a simd directive.
388*0a6a1f1dSLionel Sambuc // OpenMP [2.11.1, task Construct, Restrictions]
389*0a6a1f1dSLionel Sambuc // At most one if clause can appear on the directive.
390*0a6a1f1dSLionel Sambuc // At most one final clause can appear on the directive.
391f4a2713aSLionel Sambuc if (!FirstClause) {
392*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
393*0a6a1f1dSLionel Sambuc << getOpenMPClauseName(CKind);
394*0a6a1f1dSLionel Sambuc ErrorFound = true;
395*0a6a1f1dSLionel Sambuc }
396*0a6a1f1dSLionel Sambuc
397*0a6a1f1dSLionel Sambuc Clause = ParseOpenMPSingleExprClause(CKind);
398*0a6a1f1dSLionel Sambuc break;
399*0a6a1f1dSLionel Sambuc case OMPC_default:
400*0a6a1f1dSLionel Sambuc case OMPC_proc_bind:
401*0a6a1f1dSLionel Sambuc // OpenMP [2.14.3.1, Restrictions]
402*0a6a1f1dSLionel Sambuc // Only a single default clause may be specified on a parallel, task or
403*0a6a1f1dSLionel Sambuc // teams directive.
404*0a6a1f1dSLionel Sambuc // OpenMP [2.5, parallel Construct, Restrictions]
405*0a6a1f1dSLionel Sambuc // At most one proc_bind clause can appear on the directive.
406*0a6a1f1dSLionel Sambuc if (!FirstClause) {
407*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
408*0a6a1f1dSLionel Sambuc << getOpenMPClauseName(CKind);
409*0a6a1f1dSLionel Sambuc ErrorFound = true;
410f4a2713aSLionel Sambuc }
411f4a2713aSLionel Sambuc
412f4a2713aSLionel Sambuc Clause = ParseOpenMPSimpleClause(CKind);
413f4a2713aSLionel Sambuc break;
414*0a6a1f1dSLionel Sambuc case OMPC_schedule:
415*0a6a1f1dSLionel Sambuc // OpenMP [2.7.1, Restrictions, p. 3]
416*0a6a1f1dSLionel Sambuc // Only one schedule clause can appear on a loop directive.
417*0a6a1f1dSLionel Sambuc if (!FirstClause) {
418*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
419*0a6a1f1dSLionel Sambuc << getOpenMPClauseName(CKind);
420*0a6a1f1dSLionel Sambuc ErrorFound = true;
421*0a6a1f1dSLionel Sambuc }
422*0a6a1f1dSLionel Sambuc
423*0a6a1f1dSLionel Sambuc Clause = ParseOpenMPSingleExprWithArgClause(CKind);
424*0a6a1f1dSLionel Sambuc break;
425*0a6a1f1dSLionel Sambuc case OMPC_ordered:
426*0a6a1f1dSLionel Sambuc case OMPC_nowait:
427*0a6a1f1dSLionel Sambuc case OMPC_untied:
428*0a6a1f1dSLionel Sambuc case OMPC_mergeable:
429*0a6a1f1dSLionel Sambuc case OMPC_read:
430*0a6a1f1dSLionel Sambuc case OMPC_write:
431*0a6a1f1dSLionel Sambuc case OMPC_update:
432*0a6a1f1dSLionel Sambuc case OMPC_capture:
433*0a6a1f1dSLionel Sambuc case OMPC_seq_cst:
434*0a6a1f1dSLionel Sambuc // OpenMP [2.7.1, Restrictions, p. 9]
435*0a6a1f1dSLionel Sambuc // Only one ordered clause can appear on a loop directive.
436*0a6a1f1dSLionel Sambuc // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
437*0a6a1f1dSLionel Sambuc // Only one nowait clause can appear on a for directive.
438*0a6a1f1dSLionel Sambuc if (!FirstClause) {
439*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
440*0a6a1f1dSLionel Sambuc << getOpenMPClauseName(CKind);
441*0a6a1f1dSLionel Sambuc ErrorFound = true;
442*0a6a1f1dSLionel Sambuc }
443*0a6a1f1dSLionel Sambuc
444*0a6a1f1dSLionel Sambuc Clause = ParseOpenMPClause(CKind);
445*0a6a1f1dSLionel Sambuc break;
446f4a2713aSLionel Sambuc case OMPC_private:
447f4a2713aSLionel Sambuc case OMPC_firstprivate:
448*0a6a1f1dSLionel Sambuc case OMPC_lastprivate:
449f4a2713aSLionel Sambuc case OMPC_shared:
450*0a6a1f1dSLionel Sambuc case OMPC_reduction:
451*0a6a1f1dSLionel Sambuc case OMPC_linear:
452*0a6a1f1dSLionel Sambuc case OMPC_aligned:
453*0a6a1f1dSLionel Sambuc case OMPC_copyin:
454*0a6a1f1dSLionel Sambuc case OMPC_copyprivate:
455*0a6a1f1dSLionel Sambuc case OMPC_flush:
456f4a2713aSLionel Sambuc Clause = ParseOpenMPVarListClause(CKind);
457f4a2713aSLionel Sambuc break;
458f4a2713aSLionel Sambuc case OMPC_unknown:
459f4a2713aSLionel Sambuc Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
460f4a2713aSLionel Sambuc << getOpenMPDirectiveName(DKind);
461f4a2713aSLionel Sambuc SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
462f4a2713aSLionel Sambuc break;
463f4a2713aSLionel Sambuc case OMPC_threadprivate:
464*0a6a1f1dSLionel Sambuc Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
465*0a6a1f1dSLionel Sambuc << getOpenMPDirectiveName(DKind);
466f4a2713aSLionel Sambuc SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
467f4a2713aSLionel Sambuc break;
468f4a2713aSLionel Sambuc }
469*0a6a1f1dSLionel Sambuc return ErrorFound ? nullptr : Clause;
470f4a2713aSLionel Sambuc }
471f4a2713aSLionel Sambuc
472*0a6a1f1dSLionel Sambuc /// \brief Parsing of OpenMP clauses with single expressions like 'if',
473*0a6a1f1dSLionel Sambuc /// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
474*0a6a1f1dSLionel Sambuc /// 'thread_limit'.
475*0a6a1f1dSLionel Sambuc ///
476*0a6a1f1dSLionel Sambuc /// if-clause:
477*0a6a1f1dSLionel Sambuc /// 'if' '(' expression ')'
478*0a6a1f1dSLionel Sambuc ///
479*0a6a1f1dSLionel Sambuc /// final-clause:
480*0a6a1f1dSLionel Sambuc /// 'final' '(' expression ')'
481*0a6a1f1dSLionel Sambuc ///
482*0a6a1f1dSLionel Sambuc /// num_threads-clause:
483*0a6a1f1dSLionel Sambuc /// 'num_threads' '(' expression ')'
484*0a6a1f1dSLionel Sambuc ///
485*0a6a1f1dSLionel Sambuc /// safelen-clause:
486*0a6a1f1dSLionel Sambuc /// 'safelen' '(' expression ')'
487*0a6a1f1dSLionel Sambuc ///
488*0a6a1f1dSLionel Sambuc /// collapse-clause:
489*0a6a1f1dSLionel Sambuc /// 'collapse' '(' expression ')'
490*0a6a1f1dSLionel Sambuc ///
ParseOpenMPSingleExprClause(OpenMPClauseKind Kind)491*0a6a1f1dSLionel Sambuc OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
492*0a6a1f1dSLionel Sambuc SourceLocation Loc = ConsumeToken();
493*0a6a1f1dSLionel Sambuc
494*0a6a1f1dSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
495*0a6a1f1dSLionel Sambuc if (T.expectAndConsume(diag::err_expected_lparen_after,
496*0a6a1f1dSLionel Sambuc getOpenMPClauseName(Kind)))
497*0a6a1f1dSLionel Sambuc return nullptr;
498*0a6a1f1dSLionel Sambuc
499*0a6a1f1dSLionel Sambuc ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
500*0a6a1f1dSLionel Sambuc ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
501*0a6a1f1dSLionel Sambuc
502*0a6a1f1dSLionel Sambuc // Parse ')'.
503*0a6a1f1dSLionel Sambuc T.consumeClose();
504*0a6a1f1dSLionel Sambuc
505*0a6a1f1dSLionel Sambuc if (Val.isInvalid())
506*0a6a1f1dSLionel Sambuc return nullptr;
507*0a6a1f1dSLionel Sambuc
508*0a6a1f1dSLionel Sambuc return Actions.ActOnOpenMPSingleExprClause(
509*0a6a1f1dSLionel Sambuc Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
510*0a6a1f1dSLionel Sambuc }
511*0a6a1f1dSLionel Sambuc
512*0a6a1f1dSLionel Sambuc /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
513f4a2713aSLionel Sambuc ///
514f4a2713aSLionel Sambuc /// default-clause:
515f4a2713aSLionel Sambuc /// 'default' '(' 'none' | 'shared' ')
516f4a2713aSLionel Sambuc ///
517*0a6a1f1dSLionel Sambuc /// proc_bind-clause:
518*0a6a1f1dSLionel Sambuc /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
519*0a6a1f1dSLionel Sambuc ///
ParseOpenMPSimpleClause(OpenMPClauseKind Kind)520f4a2713aSLionel Sambuc OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
521f4a2713aSLionel Sambuc SourceLocation Loc = Tok.getLocation();
522f4a2713aSLionel Sambuc SourceLocation LOpen = ConsumeToken();
523f4a2713aSLionel Sambuc // Parse '('.
524f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
525f4a2713aSLionel Sambuc if (T.expectAndConsume(diag::err_expected_lparen_after,
526f4a2713aSLionel Sambuc getOpenMPClauseName(Kind)))
527*0a6a1f1dSLionel Sambuc return nullptr;
528f4a2713aSLionel Sambuc
529*0a6a1f1dSLionel Sambuc unsigned Type = getOpenMPSimpleClauseType(
530*0a6a1f1dSLionel Sambuc Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
531f4a2713aSLionel Sambuc SourceLocation TypeLoc = Tok.getLocation();
532f4a2713aSLionel Sambuc if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
533f4a2713aSLionel Sambuc Tok.isNot(tok::annot_pragma_openmp_end))
534f4a2713aSLionel Sambuc ConsumeAnyToken();
535f4a2713aSLionel Sambuc
536f4a2713aSLionel Sambuc // Parse ')'.
537f4a2713aSLionel Sambuc T.consumeClose();
538f4a2713aSLionel Sambuc
539f4a2713aSLionel Sambuc return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
540f4a2713aSLionel Sambuc Tok.getLocation());
541f4a2713aSLionel Sambuc }
542f4a2713aSLionel Sambuc
543*0a6a1f1dSLionel Sambuc /// \brief Parsing of OpenMP clauses like 'ordered'.
544*0a6a1f1dSLionel Sambuc ///
545*0a6a1f1dSLionel Sambuc /// ordered-clause:
546*0a6a1f1dSLionel Sambuc /// 'ordered'
547*0a6a1f1dSLionel Sambuc ///
548*0a6a1f1dSLionel Sambuc /// nowait-clause:
549*0a6a1f1dSLionel Sambuc /// 'nowait'
550*0a6a1f1dSLionel Sambuc ///
551*0a6a1f1dSLionel Sambuc /// untied-clause:
552*0a6a1f1dSLionel Sambuc /// 'untied'
553*0a6a1f1dSLionel Sambuc ///
554*0a6a1f1dSLionel Sambuc /// mergeable-clause:
555*0a6a1f1dSLionel Sambuc /// 'mergeable'
556*0a6a1f1dSLionel Sambuc ///
557*0a6a1f1dSLionel Sambuc /// read-clause:
558*0a6a1f1dSLionel Sambuc /// 'read'
559*0a6a1f1dSLionel Sambuc ///
ParseOpenMPClause(OpenMPClauseKind Kind)560*0a6a1f1dSLionel Sambuc OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
561*0a6a1f1dSLionel Sambuc SourceLocation Loc = Tok.getLocation();
562*0a6a1f1dSLionel Sambuc ConsumeAnyToken();
563*0a6a1f1dSLionel Sambuc
564*0a6a1f1dSLionel Sambuc return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
565*0a6a1f1dSLionel Sambuc }
566*0a6a1f1dSLionel Sambuc
567*0a6a1f1dSLionel Sambuc
568*0a6a1f1dSLionel Sambuc /// \brief Parsing of OpenMP clauses with single expressions and some additional
569*0a6a1f1dSLionel Sambuc /// argument like 'schedule' or 'dist_schedule'.
570*0a6a1f1dSLionel Sambuc ///
571*0a6a1f1dSLionel Sambuc /// schedule-clause:
572*0a6a1f1dSLionel Sambuc /// 'schedule' '(' kind [',' expression ] ')'
573*0a6a1f1dSLionel Sambuc ///
ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind)574*0a6a1f1dSLionel Sambuc OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
575*0a6a1f1dSLionel Sambuc SourceLocation Loc = ConsumeToken();
576*0a6a1f1dSLionel Sambuc SourceLocation CommaLoc;
577*0a6a1f1dSLionel Sambuc // Parse '('.
578*0a6a1f1dSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
579*0a6a1f1dSLionel Sambuc if (T.expectAndConsume(diag::err_expected_lparen_after,
580*0a6a1f1dSLionel Sambuc getOpenMPClauseName(Kind)))
581*0a6a1f1dSLionel Sambuc return nullptr;
582*0a6a1f1dSLionel Sambuc
583*0a6a1f1dSLionel Sambuc ExprResult Val;
584*0a6a1f1dSLionel Sambuc unsigned Type = getOpenMPSimpleClauseType(
585*0a6a1f1dSLionel Sambuc Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
586*0a6a1f1dSLionel Sambuc SourceLocation KLoc = Tok.getLocation();
587*0a6a1f1dSLionel Sambuc if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
588*0a6a1f1dSLionel Sambuc Tok.isNot(tok::annot_pragma_openmp_end))
589*0a6a1f1dSLionel Sambuc ConsumeAnyToken();
590*0a6a1f1dSLionel Sambuc
591*0a6a1f1dSLionel Sambuc if (Kind == OMPC_schedule &&
592*0a6a1f1dSLionel Sambuc (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
593*0a6a1f1dSLionel Sambuc Type == OMPC_SCHEDULE_guided) &&
594*0a6a1f1dSLionel Sambuc Tok.is(tok::comma)) {
595*0a6a1f1dSLionel Sambuc CommaLoc = ConsumeAnyToken();
596*0a6a1f1dSLionel Sambuc ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
597*0a6a1f1dSLionel Sambuc Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
598*0a6a1f1dSLionel Sambuc if (Val.isInvalid())
599*0a6a1f1dSLionel Sambuc return nullptr;
600*0a6a1f1dSLionel Sambuc }
601*0a6a1f1dSLionel Sambuc
602*0a6a1f1dSLionel Sambuc // Parse ')'.
603*0a6a1f1dSLionel Sambuc T.consumeClose();
604*0a6a1f1dSLionel Sambuc
605*0a6a1f1dSLionel Sambuc return Actions.ActOnOpenMPSingleExprWithArgClause(
606*0a6a1f1dSLionel Sambuc Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
607*0a6a1f1dSLionel Sambuc T.getCloseLocation());
608*0a6a1f1dSLionel Sambuc }
609*0a6a1f1dSLionel Sambuc
ParseReductionId(Parser & P,CXXScopeSpec & ReductionIdScopeSpec,UnqualifiedId & ReductionId)610*0a6a1f1dSLionel Sambuc static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
611*0a6a1f1dSLionel Sambuc UnqualifiedId &ReductionId) {
612*0a6a1f1dSLionel Sambuc SourceLocation TemplateKWLoc;
613*0a6a1f1dSLionel Sambuc if (ReductionIdScopeSpec.isEmpty()) {
614*0a6a1f1dSLionel Sambuc auto OOK = OO_None;
615*0a6a1f1dSLionel Sambuc switch (P.getCurToken().getKind()) {
616*0a6a1f1dSLionel Sambuc case tok::plus:
617*0a6a1f1dSLionel Sambuc OOK = OO_Plus;
618*0a6a1f1dSLionel Sambuc break;
619*0a6a1f1dSLionel Sambuc case tok::minus:
620*0a6a1f1dSLionel Sambuc OOK = OO_Minus;
621*0a6a1f1dSLionel Sambuc break;
622*0a6a1f1dSLionel Sambuc case tok::star:
623*0a6a1f1dSLionel Sambuc OOK = OO_Star;
624*0a6a1f1dSLionel Sambuc break;
625*0a6a1f1dSLionel Sambuc case tok::amp:
626*0a6a1f1dSLionel Sambuc OOK = OO_Amp;
627*0a6a1f1dSLionel Sambuc break;
628*0a6a1f1dSLionel Sambuc case tok::pipe:
629*0a6a1f1dSLionel Sambuc OOK = OO_Pipe;
630*0a6a1f1dSLionel Sambuc break;
631*0a6a1f1dSLionel Sambuc case tok::caret:
632*0a6a1f1dSLionel Sambuc OOK = OO_Caret;
633*0a6a1f1dSLionel Sambuc break;
634*0a6a1f1dSLionel Sambuc case tok::ampamp:
635*0a6a1f1dSLionel Sambuc OOK = OO_AmpAmp;
636*0a6a1f1dSLionel Sambuc break;
637*0a6a1f1dSLionel Sambuc case tok::pipepipe:
638*0a6a1f1dSLionel Sambuc OOK = OO_PipePipe;
639*0a6a1f1dSLionel Sambuc break;
640*0a6a1f1dSLionel Sambuc default:
641*0a6a1f1dSLionel Sambuc break;
642*0a6a1f1dSLionel Sambuc }
643*0a6a1f1dSLionel Sambuc if (OOK != OO_None) {
644*0a6a1f1dSLionel Sambuc SourceLocation OpLoc = P.ConsumeToken();
645*0a6a1f1dSLionel Sambuc SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
646*0a6a1f1dSLionel Sambuc ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
647*0a6a1f1dSLionel Sambuc return false;
648*0a6a1f1dSLionel Sambuc }
649*0a6a1f1dSLionel Sambuc }
650*0a6a1f1dSLionel Sambuc return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
651*0a6a1f1dSLionel Sambuc /*AllowDestructorName*/ false,
652*0a6a1f1dSLionel Sambuc /*AllowConstructorName*/ false, ParsedType(),
653*0a6a1f1dSLionel Sambuc TemplateKWLoc, ReductionId);
654*0a6a1f1dSLionel Sambuc }
655*0a6a1f1dSLionel Sambuc
656*0a6a1f1dSLionel Sambuc /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
657*0a6a1f1dSLionel Sambuc /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
658f4a2713aSLionel Sambuc ///
659f4a2713aSLionel Sambuc /// private-clause:
660f4a2713aSLionel Sambuc /// 'private' '(' list ')'
661f4a2713aSLionel Sambuc /// firstprivate-clause:
662f4a2713aSLionel Sambuc /// 'firstprivate' '(' list ')'
663*0a6a1f1dSLionel Sambuc /// lastprivate-clause:
664*0a6a1f1dSLionel Sambuc /// 'lastprivate' '(' list ')'
665f4a2713aSLionel Sambuc /// shared-clause:
666f4a2713aSLionel Sambuc /// 'shared' '(' list ')'
667*0a6a1f1dSLionel Sambuc /// linear-clause:
668*0a6a1f1dSLionel Sambuc /// 'linear' '(' list [ ':' linear-step ] ')'
669*0a6a1f1dSLionel Sambuc /// aligned-clause:
670*0a6a1f1dSLionel Sambuc /// 'aligned' '(' list [ ':' alignment ] ')'
671*0a6a1f1dSLionel Sambuc /// reduction-clause:
672*0a6a1f1dSLionel Sambuc /// 'reduction' '(' reduction-identifier ':' list ')'
673*0a6a1f1dSLionel Sambuc /// copyprivate-clause:
674*0a6a1f1dSLionel Sambuc /// 'copyprivate' '(' list ')'
675*0a6a1f1dSLionel Sambuc /// flush-clause:
676*0a6a1f1dSLionel Sambuc /// 'flush' '(' list ')'
677f4a2713aSLionel Sambuc ///
ParseOpenMPVarListClause(OpenMPClauseKind Kind)678f4a2713aSLionel Sambuc OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
679f4a2713aSLionel Sambuc SourceLocation Loc = Tok.getLocation();
680f4a2713aSLionel Sambuc SourceLocation LOpen = ConsumeToken();
681*0a6a1f1dSLionel Sambuc SourceLocation ColonLoc = SourceLocation();
682*0a6a1f1dSLionel Sambuc // Optional scope specifier and unqualified id for reduction identifier.
683*0a6a1f1dSLionel Sambuc CXXScopeSpec ReductionIdScopeSpec;
684*0a6a1f1dSLionel Sambuc UnqualifiedId ReductionId;
685*0a6a1f1dSLionel Sambuc bool InvalidReductionId = false;
686f4a2713aSLionel Sambuc // Parse '('.
687f4a2713aSLionel Sambuc BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
688f4a2713aSLionel Sambuc if (T.expectAndConsume(diag::err_expected_lparen_after,
689f4a2713aSLionel Sambuc getOpenMPClauseName(Kind)))
690*0a6a1f1dSLionel Sambuc return nullptr;
691*0a6a1f1dSLionel Sambuc
692*0a6a1f1dSLionel Sambuc // Handle reduction-identifier for reduction clause.
693*0a6a1f1dSLionel Sambuc if (Kind == OMPC_reduction) {
694*0a6a1f1dSLionel Sambuc ColonProtectionRAIIObject ColonRAII(*this);
695*0a6a1f1dSLionel Sambuc if (getLangOpts().CPlusPlus) {
696*0a6a1f1dSLionel Sambuc ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
697*0a6a1f1dSLionel Sambuc }
698*0a6a1f1dSLionel Sambuc InvalidReductionId =
699*0a6a1f1dSLionel Sambuc ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
700*0a6a1f1dSLionel Sambuc if (InvalidReductionId) {
701*0a6a1f1dSLionel Sambuc SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
702*0a6a1f1dSLionel Sambuc StopBeforeMatch);
703*0a6a1f1dSLionel Sambuc }
704*0a6a1f1dSLionel Sambuc if (Tok.is(tok::colon)) {
705*0a6a1f1dSLionel Sambuc ColonLoc = ConsumeToken();
706*0a6a1f1dSLionel Sambuc } else {
707*0a6a1f1dSLionel Sambuc Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
708*0a6a1f1dSLionel Sambuc }
709*0a6a1f1dSLionel Sambuc }
710f4a2713aSLionel Sambuc
711f4a2713aSLionel Sambuc SmallVector<Expr *, 5> Vars;
712*0a6a1f1dSLionel Sambuc bool IsComma = !InvalidReductionId;
713*0a6a1f1dSLionel Sambuc const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
714*0a6a1f1dSLionel Sambuc while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
715f4a2713aSLionel Sambuc Tok.isNot(tok::annot_pragma_openmp_end))) {
716*0a6a1f1dSLionel Sambuc ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
717f4a2713aSLionel Sambuc // Parse variable
718*0a6a1f1dSLionel Sambuc ExprResult VarExpr =
719*0a6a1f1dSLionel Sambuc Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
720f4a2713aSLionel Sambuc if (VarExpr.isUsable()) {
721*0a6a1f1dSLionel Sambuc Vars.push_back(VarExpr.get());
722f4a2713aSLionel Sambuc } else {
723f4a2713aSLionel Sambuc SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
724f4a2713aSLionel Sambuc StopBeforeMatch);
725f4a2713aSLionel Sambuc }
726f4a2713aSLionel Sambuc // Skip ',' if any
727f4a2713aSLionel Sambuc IsComma = Tok.is(tok::comma);
728*0a6a1f1dSLionel Sambuc if (IsComma)
729f4a2713aSLionel Sambuc ConsumeToken();
730*0a6a1f1dSLionel Sambuc else if (Tok.isNot(tok::r_paren) &&
731*0a6a1f1dSLionel Sambuc Tok.isNot(tok::annot_pragma_openmp_end) &&
732*0a6a1f1dSLionel Sambuc (!MayHaveTail || Tok.isNot(tok::colon)))
733f4a2713aSLionel Sambuc Diag(Tok, diag::err_omp_expected_punc)
734*0a6a1f1dSLionel Sambuc << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
735*0a6a1f1dSLionel Sambuc : getOpenMPClauseName(Kind))
736*0a6a1f1dSLionel Sambuc << (Kind == OMPC_flush);
737f4a2713aSLionel Sambuc }
738*0a6a1f1dSLionel Sambuc
739*0a6a1f1dSLionel Sambuc // Parse ':' linear-step (or ':' alignment).
740*0a6a1f1dSLionel Sambuc Expr *TailExpr = nullptr;
741*0a6a1f1dSLionel Sambuc const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
742*0a6a1f1dSLionel Sambuc if (MustHaveTail) {
743*0a6a1f1dSLionel Sambuc ColonLoc = Tok.getLocation();
744*0a6a1f1dSLionel Sambuc ConsumeToken();
745*0a6a1f1dSLionel Sambuc ExprResult Tail =
746*0a6a1f1dSLionel Sambuc Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
747*0a6a1f1dSLionel Sambuc if (Tail.isUsable())
748*0a6a1f1dSLionel Sambuc TailExpr = Tail.get();
749*0a6a1f1dSLionel Sambuc else
750*0a6a1f1dSLionel Sambuc SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
751*0a6a1f1dSLionel Sambuc StopBeforeMatch);
752f4a2713aSLionel Sambuc }
753f4a2713aSLionel Sambuc
754f4a2713aSLionel Sambuc // Parse ')'.
755f4a2713aSLionel Sambuc T.consumeClose();
756*0a6a1f1dSLionel Sambuc if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
757*0a6a1f1dSLionel Sambuc return nullptr;
758f4a2713aSLionel Sambuc
759*0a6a1f1dSLionel Sambuc return Actions.ActOnOpenMPVarListClause(
760*0a6a1f1dSLionel Sambuc Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
761*0a6a1f1dSLionel Sambuc ReductionIdScopeSpec,
762*0a6a1f1dSLionel Sambuc ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
763*0a6a1f1dSLionel Sambuc : DeclarationNameInfo());
764f4a2713aSLionel Sambuc }
765f4a2713aSLionel Sambuc
766