blob: a4b97e173be49c1cca69520103cba527c1013765 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Expression parsing implementation for C++.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/Diagnostic.h"
15#include "clang/Parse/Parser.h"
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +000016#include "clang/Parse/DeclSpec.h"
Sebastian Redla55e52c2008-11-25 22:21:31 +000017#include "AstGuard.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000018using namespace clang;
19
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000020/// MaybeParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
21/// Returns true if a nested-name-specifier was parsed from the token stream.
Chris Lattner55a7cef2009-01-05 00:13:00 +000022///
23/// Note that this routine emits an error if you call it with ::new or ::delete
24/// as the current tokens, so only call it in contexts where these are invalid.
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000025///
26/// '::'[opt] nested-name-specifier
27/// '::'
28///
29/// nested-name-specifier:
30/// type-name '::'
31/// namespace-name '::'
32/// nested-name-specifier identifier '::'
33/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
34///
Chris Lattnera7bc7c82009-01-04 23:23:14 +000035bool Parser::MaybeParseCXXScopeSpecifier(CXXScopeSpec &SS,
36 const Token *GlobalQualifier) {
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000037 assert(getLang().CPlusPlus &&
Chris Lattner7452c6f2009-01-05 01:24:05 +000038 "Call sites of this function should be guarded by checking for C++");
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000039
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000040 if (Tok.is(tok::annot_cxxscope)) {
Chris Lattnera7bc7c82009-01-04 23:23:14 +000041 assert(GlobalQualifier == 0 &&
Chris Lattner55a7cef2009-01-05 00:13:00 +000042 "Cannot have :: followed by a resolved annotation scope");
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000043 SS.setScopeRep(Tok.getAnnotationValue());
44 SS.setRange(Tok.getAnnotationRange());
45 ConsumeToken();
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000046 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000047 }
Chris Lattnere607e802009-01-04 21:14:15 +000048
Chris Lattnera7bc7c82009-01-04 23:23:14 +000049 if (GlobalQualifier == 0 &&
50 Tok.isNot(tok::coloncolon) &&
Chris Lattnere607e802009-01-04 21:14:15 +000051 (Tok.isNot(tok::identifier) || NextToken().isNot(tok::coloncolon)))
52 return false;
53
Chris Lattnera7bc7c82009-01-04 23:23:14 +000054 if (GlobalQualifier) {
55 // Pre-parsed '::'.
56 SS.setBeginLoc(GlobalQualifier->getLocation());
57 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope,
58 GlobalQualifier->getLocation()));
59 SS.setEndLoc(GlobalQualifier->getLocation());
Chris Lattner55a7cef2009-01-05 00:13:00 +000060
61 assert(Tok.isNot(tok::kw_new) && Tok.isNot(tok::kw_delete) &&
62 "Never called with preparsed :: qualifier and with new/delete");
Chris Lattnera7bc7c82009-01-04 23:23:14 +000063 } else {
64 SS.setBeginLoc(Tok.getLocation());
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000065
Chris Lattner55a7cef2009-01-05 00:13:00 +000066 // '::' - Global scope qualifier.
Chris Lattnera7bc7c82009-01-04 23:23:14 +000067 if (Tok.is(tok::coloncolon)) {
Chris Lattnera7bc7c82009-01-04 23:23:14 +000068 SourceLocation CCLoc = ConsumeToken();
Chris Lattner55a7cef2009-01-05 00:13:00 +000069
70 // ::new and ::delete aren't nested-name-specifiers, and
71 // MaybeParseCXXScopeSpecifier is never called in a context where one could
72 // exist. This means that if we see it, we have a syntax error.
73 if (Tok.is(tok::kw_new) || Tok.is(tok::kw_delete)) {
74 Diag(Tok, diag::err_invalid_qualified_new_delete)
75 << Tok.is(tok::kw_delete);
76 SS.setBeginLoc(SourceLocation());
77 return false;
78 }
79
80 // Global scope.
Chris Lattnera7bc7c82009-01-04 23:23:14 +000081 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
82 SS.setEndLoc(CCLoc);
83 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000084 }
85
86 // nested-name-specifier:
87 // type-name '::'
88 // namespace-name '::'
89 // nested-name-specifier identifier '::'
90 // nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000091 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
92 IdentifierInfo *II = Tok.getIdentifierInfo();
93 SourceLocation IdLoc = ConsumeToken();
Chris Lattnere607e802009-01-04 21:14:15 +000094 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000095 SourceLocation CCLoc = ConsumeToken();
96 if (SS.isInvalid())
97 continue;
98
99 SS.setScopeRep(
Chris Lattnere607e802009-01-04 21:14:15 +0000100 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000101 SS.setEndLoc(CCLoc);
102 }
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +0000103
104 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000105}
106
107/// ParseCXXIdExpression - Handle id-expression.
108///
109/// id-expression:
110/// unqualified-id
111/// qualified-id
112///
113/// unqualified-id:
114/// identifier
115/// operator-function-id
116/// conversion-function-id [TODO]
117/// '~' class-name [TODO]
118/// template-id [TODO]
119///
120/// qualified-id:
121/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
122/// '::' identifier
123/// '::' operator-function-id
124/// '::' template-id [TODO]
125///
126/// nested-name-specifier:
127/// type-name '::'
128/// namespace-name '::'
129/// nested-name-specifier identifier '::'
130/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
131///
132/// NOTE: The standard specifies that, for qualified-id, the parser does not
133/// expect:
134///
135/// '::' conversion-function-id
136/// '::' '~' class-name
137///
138/// This may cause a slight inconsistency on diagnostics:
139///
140/// class C {};
141/// namespace A {}
142/// void f() {
143/// :: A :: ~ C(); // Some Sema error about using destructor with a
144/// // namespace.
145/// :: ~ C(); // Some Parser error like 'unexpected ~'.
146/// }
147///
148/// We simplify the parser a bit and make it work like:
149///
150/// qualified-id:
151/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
152/// '::' unqualified-id
153///
154/// That way Sema can handle and report similar errors for namespaces and the
155/// global scope.
156///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000157Parser::OwningExprResult Parser::ParseCXXIdExpression() {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000158 // qualified-id:
159 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
160 // '::' unqualified-id
161 //
162 CXXScopeSpec SS;
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +0000163 MaybeParseCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000164
165 // unqualified-id:
166 // identifier
167 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000168 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000169 // '~' class-name [TODO]
170 // template-id [TODO]
171 //
172 switch (Tok.getKind()) {
173 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000174 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000175
176 case tok::identifier: {
177 // Consume the identifier so that we can see if it is followed by a '('.
178 IdentifierInfo &II = *Tok.getIdentifierInfo();
179 SourceLocation L = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000180 return Owned(Actions.ActOnIdentifierExpr(CurScope, L, II,
181 Tok.is(tok::l_paren), &SS));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000182 }
183
184 case tok::kw_operator: {
185 SourceLocation OperatorLoc = Tok.getLocation();
Chris Lattner7452c6f2009-01-05 01:24:05 +0000186 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000187 return Owned(Actions.ActOnCXXOperatorFunctionIdExpr(
188 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS));
Chris Lattner7452c6f2009-01-05 01:24:05 +0000189 if (TypeTy *Type = ParseConversionFunctionId())
190 return Owned(Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc,
191 Type,
192 Tok.is(tok::l_paren), SS));
Sebastian Redl20df9b72008-12-11 22:51:44 +0000193
Douglas Gregor2def4832008-11-17 20:34:05 +0000194 // We already complained about a bad conversion-function-id,
195 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000196 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000197 }
198
199 } // switch.
200
201 assert(0 && "The switch was supposed to take care everything.");
202}
203
Reid Spencer5f016e22007-07-11 17:01:13 +0000204/// ParseCXXCasts - This handles the various ways to cast expressions to another
205/// type.
206///
207/// postfix-expression: [C++ 5.2p1]
208/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
209/// 'static_cast' '<' type-name '>' '(' expression ')'
210/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
211/// 'const_cast' '<' type-name '>' '(' expression ')'
212///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000213Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000214 tok::TokenKind Kind = Tok.getKind();
215 const char *CastName = 0; // For error messages
216
217 switch (Kind) {
218 default: assert(0 && "Unknown C++ cast!"); abort();
219 case tok::kw_const_cast: CastName = "const_cast"; break;
220 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
221 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
222 case tok::kw_static_cast: CastName = "static_cast"; break;
223 }
224
225 SourceLocation OpLoc = ConsumeToken();
226 SourceLocation LAngleBracketLoc = Tok.getLocation();
227
228 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000229 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000230
231 TypeTy *CastTy = ParseTypeName();
232 SourceLocation RAngleBracketLoc = Tok.getLocation();
233
Chris Lattner1ab3b962008-11-18 07:48:38 +0000234 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000235 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000236
237 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
238
Chris Lattner1ab3b962008-11-18 07:48:38 +0000239 if (Tok.isNot(tok::l_paren))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000240 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName);
Reid Spencer5f016e22007-07-11 17:01:13 +0000241
Sebastian Redld8c4e152008-12-11 22:33:27 +0000242 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
Reid Spencer5f016e22007-07-11 17:01:13 +0000243
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000244 if (!Result.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000245 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
246 LAngleBracketLoc, CastTy, RAngleBracketLoc,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000247 LParenLoc, Result.release(), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000248
Sebastian Redl20df9b72008-12-11 22:51:44 +0000249 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000250}
251
Sebastian Redlc42e1182008-11-11 11:37:55 +0000252/// ParseCXXTypeid - This handles the C++ typeid expression.
253///
254/// postfix-expression: [C++ 5.2p1]
255/// 'typeid' '(' expression ')'
256/// 'typeid' '(' type-id ')'
257///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000258Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000259 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
260
261 SourceLocation OpLoc = ConsumeToken();
262 SourceLocation LParenLoc = Tok.getLocation();
263 SourceLocation RParenLoc;
264
265 // typeid expressions are always parenthesized.
266 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
267 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000268 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000269
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000270 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000271
272 if (isTypeIdInParens()) {
273 TypeTy *Ty = ParseTypeName();
274
275 // Match the ')'.
276 MatchRHSPunctuation(tok::r_paren, LParenLoc);
277
278 if (!Ty)
Sebastian Redl20df9b72008-12-11 22:51:44 +0000279 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000280
281 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
282 Ty, RParenLoc);
283 } else {
284 Result = ParseExpression();
285
286 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000287 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000288 SkipUntil(tok::r_paren);
289 else {
290 MatchRHSPunctuation(tok::r_paren, LParenLoc);
291
292 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000293 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000294 }
295 }
296
Sebastian Redl20df9b72008-12-11 22:51:44 +0000297 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000298}
299
Reid Spencer5f016e22007-07-11 17:01:13 +0000300/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
301///
302/// boolean-literal: [C++ 2.13.5]
303/// 'true'
304/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000305Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000306 tok::TokenKind Kind = Tok.getKind();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000307 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind));
Reid Spencer5f016e22007-07-11 17:01:13 +0000308}
Chris Lattner50dd2892008-02-26 00:51:44 +0000309
310/// ParseThrowExpression - This handles the C++ throw expression.
311///
312/// throw-expression: [C++ 15]
313/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000314Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000315 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000316 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000317
Chris Lattner2a2819a2008-04-06 06:02:23 +0000318 // If the current token isn't the start of an assignment-expression,
319 // then the expression is not present. This handles things like:
320 // "C ? throw : (void)42", which is crazy but legal.
321 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
322 case tok::semi:
323 case tok::r_paren:
324 case tok::r_square:
325 case tok::r_brace:
326 case tok::colon:
327 case tok::comma:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000328 return Owned(Actions.ActOnCXXThrow(ThrowLoc));
Chris Lattner50dd2892008-02-26 00:51:44 +0000329
Chris Lattner2a2819a2008-04-06 06:02:23 +0000330 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000331 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000332 if (Expr.isInvalid()) return move(Expr);
333 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release()));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000334 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000335}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000336
337/// ParseCXXThis - This handles the C++ 'this' pointer.
338///
339/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
340/// a non-lvalue expression whose value is the address of the object for which
341/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000342Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000343 assert(Tok.is(tok::kw_this) && "Not 'this'!");
344 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000345 return Owned(Actions.ActOnCXXThis(ThisLoc));
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000346}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000347
348/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
349/// Can be interpreted either as function-style casting ("int(x)")
350/// or class type construction ("ClassType(x,y,z)")
351/// or creation of a value-initialized type ("int()").
352///
353/// postfix-expression: [C++ 5.2p1]
354/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
355/// typename-specifier '(' expression-list[opt] ')' [TODO]
356///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000357Parser::OwningExprResult
358Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000359 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
360 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
361
362 assert(Tok.is(tok::l_paren) && "Expected '('!");
363 SourceLocation LParenLoc = ConsumeParen();
364
Sebastian Redla55e52c2008-11-25 22:21:31 +0000365 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000366 CommaLocsTy CommaLocs;
367
368 if (Tok.isNot(tok::r_paren)) {
369 if (ParseExpressionList(Exprs, CommaLocs)) {
370 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000371 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000372 }
373 }
374
375 // Match the ')'.
376 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
377
378 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
379 "Unexpected number of commas!");
Sebastian Redl20df9b72008-12-11 22:51:44 +0000380 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
381 LParenLoc,
382 Exprs.take(), Exprs.size(),
383 &CommaLocs[0], RParenLoc));
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000384}
385
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000386/// ParseCXXCondition - if/switch/while/for condition expression.
387///
388/// condition:
389/// expression
390/// type-specifier-seq declarator '=' assignment-expression
391/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
392/// '=' assignment-expression
393///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000394Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000395 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000396 return ParseExpression(); // expression
397
398 SourceLocation StartLoc = Tok.getLocation();
399
400 // type-specifier-seq
401 DeclSpec DS;
402 ParseSpecifierQualifierList(DS);
403
404 // declarator
405 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
406 ParseDeclarator(DeclaratorInfo);
407
408 // simple-asm-expr[opt]
409 if (Tok.is(tok::kw_asm)) {
Sebastian Redleffa8d12008-12-10 00:02:53 +0000410 OwningExprResult AsmLabel(ParseSimpleAsm());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000411 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000412 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000413 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000414 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000415 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000416 }
417
418 // If attributes are present, parse them.
419 if (Tok.is(tok::kw___attribute))
420 DeclaratorInfo.AddAttributes(ParseAttributes());
421
422 // '=' assignment-expression
423 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000424 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000425 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000426 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000427 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000428 return ExprError();
429
430 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
431 DeclaratorInfo,EqualLoc,
432 AssignExpr.release()));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000433}
434
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000435/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
436/// This should only be called when the current token is known to be part of
437/// simple-type-specifier.
438///
439/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000440/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000441/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
442/// char
443/// wchar_t
444/// bool
445/// short
446/// int
447/// long
448/// signed
449/// unsigned
450/// float
451/// double
452/// void
453/// [GNU] typeof-specifier
454/// [C++0x] auto [TODO]
455///
456/// type-name:
457/// class-name
458/// enum-name
459/// typedef-name
460///
461void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
462 DS.SetRangeStart(Tok.getLocation());
463 const char *PrevSpec;
464 SourceLocation Loc = Tok.getLocation();
465
466 switch (Tok.getKind()) {
Chris Lattner55a7cef2009-01-05 00:13:00 +0000467 case tok::identifier: // foo::bar
468 case tok::coloncolon: // ::foo::bar
469 assert(0 && "Annotation token should already be formed!");
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000470 default:
471 assert(0 && "Not a simple-type-specifier token!");
472 abort();
Chris Lattner55a7cef2009-01-05 00:13:00 +0000473
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000474 // type-name
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000475 case tok::annot_qualtypename: {
476 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
477 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000478 break;
479 }
480
481 // builtin types
482 case tok::kw_short:
483 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
484 break;
485 case tok::kw_long:
486 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
487 break;
488 case tok::kw_signed:
489 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
490 break;
491 case tok::kw_unsigned:
492 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
493 break;
494 case tok::kw_void:
495 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
496 break;
497 case tok::kw_char:
498 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
499 break;
500 case tok::kw_int:
501 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
502 break;
503 case tok::kw_float:
504 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
505 break;
506 case tok::kw_double:
507 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
508 break;
509 case tok::kw_wchar_t:
510 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
511 break;
512 case tok::kw_bool:
513 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
514 break;
515
516 // GNU typeof support.
517 case tok::kw_typeof:
518 ParseTypeofSpecifier(DS);
519 DS.Finish(Diags, PP.getSourceManager(), getLang());
520 return;
521 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000522 if (Tok.is(tok::annot_qualtypename))
523 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
524 else
525 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000526 ConsumeToken();
527 DS.Finish(Diags, PP.getSourceManager(), getLang());
528}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000529
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000530/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
531/// [dcl.name]), which is a non-empty sequence of type-specifiers,
532/// e.g., "const short int". Note that the DeclSpec is *not* finished
533/// by parsing the type-specifier-seq, because these sequences are
534/// typically followed by some form of declarator. Returns true and
535/// emits diagnostics if this is not a type-specifier-seq, false
536/// otherwise.
537///
538/// type-specifier-seq: [C++ 8.1]
539/// type-specifier type-specifier-seq[opt]
540///
541bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
542 DS.SetRangeStart(Tok.getLocation());
543 const char *PrevSpec = 0;
544 int isInvalid = 0;
545
546 // Parse one or more of the type specifiers.
547 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000548 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000549 return true;
550 }
Daniel Dunbarb90585c2008-11-08 04:28:37 +0000551 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000552
553 return false;
554}
555
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000556/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000557/// operator name (C++ [over.oper]). If successful, returns the
558/// predefined identifier that corresponds to that overloaded
559/// operator. Otherwise, returns NULL and does not consume any tokens.
560///
561/// operator-function-id: [C++ 13.5]
562/// 'operator' operator
563///
564/// operator: one of
565/// new delete new[] delete[]
566/// + - * / % ^ & | ~
567/// ! = < > += -= *= /= %=
568/// ^= &= |= << >> >>= <<= == !=
569/// <= >= && || ++ -- , ->* ->
570/// () []
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000571OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000572 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000573
574 OverloadedOperatorKind Op = OO_None;
575 switch (NextToken().getKind()) {
576 case tok::kw_new:
577 ConsumeToken(); // 'operator'
578 ConsumeToken(); // 'new'
579 if (Tok.is(tok::l_square)) {
580 ConsumeBracket(); // '['
581 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
582 Op = OO_Array_New;
583 } else {
584 Op = OO_New;
585 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000586 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000587
588 case tok::kw_delete:
589 ConsumeToken(); // 'operator'
590 ConsumeToken(); // 'delete'
591 if (Tok.is(tok::l_square)) {
592 ConsumeBracket(); // '['
593 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
594 Op = OO_Array_Delete;
595 } else {
596 Op = OO_Delete;
597 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000598 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000599
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000600#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000601 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000602#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000603#include "clang/Basic/OperatorKinds.def"
604
605 case tok::l_paren:
606 ConsumeToken(); // 'operator'
607 ConsumeParen(); // '('
608 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000609 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000610
611 case tok::l_square:
612 ConsumeToken(); // 'operator'
613 ConsumeBracket(); // '['
614 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000615 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000616
617 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000618 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000619 }
620
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000621 ConsumeToken(); // 'operator'
622 ConsumeAnyToken(); // the operator itself
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000623 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000624}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000625
626/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
627/// which expresses the name of a user-defined conversion operator
628/// (C++ [class.conv.fct]p1). Returns the type that this operator is
629/// specifying a conversion for, or NULL if there was an error.
630///
631/// conversion-function-id: [C++ 12.3.2]
632/// operator conversion-type-id
633///
634/// conversion-type-id:
635/// type-specifier-seq conversion-declarator[opt]
636///
637/// conversion-declarator:
638/// ptr-operator conversion-declarator[opt]
639Parser::TypeTy *Parser::ParseConversionFunctionId() {
640 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
641 ConsumeToken(); // 'operator'
642
643 // Parse the type-specifier-seq.
644 DeclSpec DS;
645 if (ParseCXXTypeSpecifierSeq(DS))
646 return 0;
647
648 // Parse the conversion-declarator, which is merely a sequence of
649 // ptr-operators.
650 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000651 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000652
653 // Finish up the type.
654 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
655 if (Result.isInvalid)
656 return 0;
657 else
658 return Result.Val;
659}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000660
661/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
662/// memory in a typesafe manner and call constructors.
Chris Lattner59232d32009-01-04 21:25:24 +0000663///
664/// This method is called to parse the new expression after the optional :: has
665/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
666/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000667///
668/// new-expression:
669/// '::'[opt] 'new' new-placement[opt] new-type-id
670/// new-initializer[opt]
671/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
672/// new-initializer[opt]
673///
674/// new-placement:
675/// '(' expression-list ')'
676///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000677/// new-type-id:
678/// type-specifier-seq new-declarator[opt]
679///
680/// new-declarator:
681/// ptr-operator new-declarator[opt]
682/// direct-new-declarator
683///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000684/// new-initializer:
685/// '(' expression-list[opt] ')'
686/// [C++0x] braced-init-list [TODO]
687///
Chris Lattner59232d32009-01-04 21:25:24 +0000688Parser::OwningExprResult
689Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
690 assert(Tok.is(tok::kw_new) && "expected 'new' token");
691 ConsumeToken(); // Consume 'new'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000692
693 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
694 // second form of new-expression. It can't be a new-type-id.
695
Sebastian Redla55e52c2008-11-25 22:21:31 +0000696 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000697 SourceLocation PlacementLParen, PlacementRParen;
698
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000699 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000700 DeclSpec DS;
701 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000702 if (Tok.is(tok::l_paren)) {
703 // If it turns out to be a placement, we change the type location.
704 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000705 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
706 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000707 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000708 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000709
710 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000711 if (PlacementRParen.isInvalid()) {
712 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000713 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000714 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000715
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000716 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000717 // Reset the placement locations. There was no placement.
718 PlacementLParen = PlacementRParen = SourceLocation();
719 ParenTypeId = true;
720 } else {
721 // We still need the type.
722 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000723 SourceLocation LParen = ConsumeParen();
724 ParseSpecifierQualifierList(DS);
725 ParseDeclarator(DeclaratorInfo);
726 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000727 ParenTypeId = true;
728 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000729 if (ParseCXXTypeSpecifierSeq(DS))
730 DeclaratorInfo.setInvalidType(true);
731 else
732 ParseDeclaratorInternal(DeclaratorInfo,
733 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000734 ParenTypeId = false;
735 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000736 }
737 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000738 // A new-type-id is a simplified type-id, where essentially the
739 // direct-declarator is replaced by a direct-new-declarator.
740 if (ParseCXXTypeSpecifierSeq(DS))
741 DeclaratorInfo.setInvalidType(true);
742 else
743 ParseDeclaratorInternal(DeclaratorInfo,
744 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000745 ParenTypeId = false;
746 }
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000747 if (DeclaratorInfo.getInvalidType()) {
748 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000749 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000750 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000751
Sebastian Redla55e52c2008-11-25 22:21:31 +0000752 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000753 SourceLocation ConstructorLParen, ConstructorRParen;
754
755 if (Tok.is(tok::l_paren)) {
756 ConstructorLParen = ConsumeParen();
757 if (Tok.isNot(tok::r_paren)) {
758 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000759 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
760 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000761 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000762 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000763 }
764 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000765 if (ConstructorRParen.isInvalid()) {
766 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000767 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000768 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000769 }
770
Sebastian Redl20df9b72008-12-11 22:51:44 +0000771 return Owned(Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
772 PlacementArgs.take(), PlacementArgs.size(),
773 PlacementRParen, ParenTypeId, DeclaratorInfo,
774 ConstructorLParen, ConstructorArgs.take(),
775 ConstructorArgs.size(), ConstructorRParen));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000776}
777
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000778/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
779/// passed to ParseDeclaratorInternal.
780///
781/// direct-new-declarator:
782/// '[' expression ']'
783/// direct-new-declarator '[' constant-expression ']'
784///
Chris Lattner59232d32009-01-04 21:25:24 +0000785void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000786 // Parse the array dimensions.
787 bool first = true;
788 while (Tok.is(tok::l_square)) {
789 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000790 OwningExprResult Size(first ? ParseExpression()
791 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000792 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000793 // Recover
794 SkipUntil(tok::r_square);
795 return;
796 }
797 first = false;
798
799 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000800 Size.release(), LLoc));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000801
802 if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
803 return;
804 }
805}
806
807/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
808/// This ambiguity appears in the syntax of the C++ new operator.
809///
810/// new-expression:
811/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
812/// new-initializer[opt]
813///
814/// new-placement:
815/// '(' expression-list ')'
816///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000817bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner59232d32009-01-04 21:25:24 +0000818 Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000819 // The '(' was already consumed.
820 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000821 ParseSpecifierQualifierList(D.getMutableDeclSpec());
822 ParseDeclarator(D);
823 return D.getInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000824 }
825
826 // It's not a type, it has to be an expression list.
827 // Discard the comma locations - ActOnCXXNew has enough parameters.
828 CommaLocsTy CommaLocs;
829 return ParseExpressionList(PlacementArgs, CommaLocs);
830}
831
832/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
833/// to free memory allocated by new.
834///
Chris Lattner59232d32009-01-04 21:25:24 +0000835/// This method is called to parse the 'delete' expression after the optional
836/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
837/// and "Start" is its location. Otherwise, "Start" is the location of the
838/// 'delete' token.
839///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000840/// delete-expression:
841/// '::'[opt] 'delete' cast-expression
842/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner59232d32009-01-04 21:25:24 +0000843Parser::OwningExprResult
844Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
845 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
846 ConsumeToken(); // Consume 'delete'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000847
848 // Array delete?
849 bool ArrayDelete = false;
850 if (Tok.is(tok::l_square)) {
851 ArrayDelete = true;
852 SourceLocation LHS = ConsumeBracket();
853 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
854 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000855 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000856 }
857
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000858 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000859 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000860 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000861
Sebastian Redl20df9b72008-12-11 22:51:44 +0000862 return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete,
863 Operand.release()));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000864}