blob: 3ff9f4427c399eaeb44537e7b3a097bd2f4fee3c [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) {
50 // Pre-parsed '::'.
51 SS.setBeginLoc(GlobalQualifier->getLocation());
52 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope,
53 GlobalQualifier->getLocation()));
54 SS.setEndLoc(GlobalQualifier->getLocation());
Chris Lattner55a7cef2009-01-05 00:13:00 +000055
56 assert(Tok.isNot(tok::kw_new) && Tok.isNot(tok::kw_delete) &&
57 "Never called with preparsed :: qualifier and with new/delete");
Chris Lattner357089d2009-01-05 02:07:19 +000058 } else if (Tok.is(tok::coloncolon)) {
Chris Lattner55a7cef2009-01-05 00:13:00 +000059 // '::' - Global scope qualifier.
Chris Lattner357089d2009-01-05 02:07:19 +000060 SourceLocation CCLoc = ConsumeToken();
Chris Lattner55a7cef2009-01-05 00:13:00 +000061
Chris Lattner357089d2009-01-05 02:07:19 +000062 // ::new and ::delete aren't nested-name-specifiers, and
63 // MaybeParseCXXScopeSpecifier is never called in a context where one
64 // could exist. This means that if we see it, we have a syntax error.
65 if (Tok.is(tok::kw_new) || Tok.is(tok::kw_delete)) {
66 Diag(Tok, diag::err_invalid_qualified_new_delete)
67 << Tok.is(tok::kw_delete);
68 return false;
Chris Lattnera7bc7c82009-01-04 23:23:14 +000069 }
Chris Lattner357089d2009-01-05 02:07:19 +000070
71 SS.setBeginLoc(CCLoc);
72 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
73 SS.setEndLoc(CCLoc);
74 } else if (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
75 SS.setBeginLoc(Tok.getLocation());
76 } else {
77 // Not a CXXScopeSpecifier.
78 return false;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000079 }
80
81 // nested-name-specifier:
82 // type-name '::'
83 // namespace-name '::'
84 // nested-name-specifier identifier '::'
85 // nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000086 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
87 IdentifierInfo *II = Tok.getIdentifierInfo();
88 SourceLocation IdLoc = ConsumeToken();
Chris Lattnere607e802009-01-04 21:14:15 +000089 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000090 SourceLocation CCLoc = ConsumeToken();
91 if (SS.isInvalid())
92 continue;
93
94 SS.setScopeRep(
Chris Lattnere607e802009-01-04 21:14:15 +000095 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +000096 SS.setEndLoc(CCLoc);
97 }
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +000098
99 return true;
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000100}
101
102/// ParseCXXIdExpression - Handle id-expression.
103///
104/// id-expression:
105/// unqualified-id
106/// qualified-id
107///
108/// unqualified-id:
109/// identifier
110/// operator-function-id
111/// conversion-function-id [TODO]
112/// '~' class-name [TODO]
113/// template-id [TODO]
114///
115/// qualified-id:
116/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
117/// '::' identifier
118/// '::' operator-function-id
119/// '::' template-id [TODO]
120///
121/// nested-name-specifier:
122/// type-name '::'
123/// namespace-name '::'
124/// nested-name-specifier identifier '::'
125/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
126///
127/// NOTE: The standard specifies that, for qualified-id, the parser does not
128/// expect:
129///
130/// '::' conversion-function-id
131/// '::' '~' class-name
132///
133/// This may cause a slight inconsistency on diagnostics:
134///
135/// class C {};
136/// namespace A {}
137/// void f() {
138/// :: A :: ~ C(); // Some Sema error about using destructor with a
139/// // namespace.
140/// :: ~ C(); // Some Parser error like 'unexpected ~'.
141/// }
142///
143/// We simplify the parser a bit and make it work like:
144///
145/// qualified-id:
146/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
147/// '::' unqualified-id
148///
149/// That way Sema can handle and report similar errors for namespaces and the
150/// global scope.
151///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000152Parser::OwningExprResult Parser::ParseCXXIdExpression() {
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000153 // qualified-id:
154 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
155 // '::' unqualified-id
156 //
157 CXXScopeSpec SS;
Argyrios Kyrtzidis4bdd91c2008-11-26 21:41:52 +0000158 MaybeParseCXXScopeSpecifier(SS);
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000159
160 // unqualified-id:
161 // identifier
162 // operator-function-id
Douglas Gregor2def4832008-11-17 20:34:05 +0000163 // conversion-function-id
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000164 // '~' class-name [TODO]
165 // template-id [TODO]
166 //
167 switch (Tok.getKind()) {
168 default:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000169 return ExprError(Diag(Tok, diag::err_expected_unqualified_id));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000170
171 case tok::identifier: {
172 // Consume the identifier so that we can see if it is followed by a '('.
173 IdentifierInfo &II = *Tok.getIdentifierInfo();
174 SourceLocation L = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000175 return Owned(Actions.ActOnIdentifierExpr(CurScope, L, II,
176 Tok.is(tok::l_paren), &SS));
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000177 }
178
179 case tok::kw_operator: {
180 SourceLocation OperatorLoc = Tok.getLocation();
Chris Lattner7452c6f2009-01-05 01:24:05 +0000181 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000182 return Owned(Actions.ActOnCXXOperatorFunctionIdExpr(
183 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS));
Chris Lattner7452c6f2009-01-05 01:24:05 +0000184 if (TypeTy *Type = ParseConversionFunctionId())
185 return Owned(Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc,
186 Type,
187 Tok.is(tok::l_paren), SS));
Sebastian Redl20df9b72008-12-11 22:51:44 +0000188
Douglas Gregor2def4832008-11-17 20:34:05 +0000189 // We already complained about a bad conversion-function-id,
190 // above.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000191 return ExprError();
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000192 }
193
194 } // switch.
195
196 assert(0 && "The switch was supposed to take care everything.");
197}
198
Reid Spencer5f016e22007-07-11 17:01:13 +0000199/// ParseCXXCasts - This handles the various ways to cast expressions to another
200/// type.
201///
202/// postfix-expression: [C++ 5.2p1]
203/// 'dynamic_cast' '<' type-name '>' '(' expression ')'
204/// 'static_cast' '<' type-name '>' '(' expression ')'
205/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
206/// 'const_cast' '<' type-name '>' '(' expression ')'
207///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000208Parser::OwningExprResult Parser::ParseCXXCasts() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000209 tok::TokenKind Kind = Tok.getKind();
210 const char *CastName = 0; // For error messages
211
212 switch (Kind) {
213 default: assert(0 && "Unknown C++ cast!"); abort();
214 case tok::kw_const_cast: CastName = "const_cast"; break;
215 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
216 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
217 case tok::kw_static_cast: CastName = "static_cast"; break;
218 }
219
220 SourceLocation OpLoc = ConsumeToken();
221 SourceLocation LAngleBracketLoc = Tok.getLocation();
222
223 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000224 return ExprError();
Reid Spencer5f016e22007-07-11 17:01:13 +0000225
226 TypeTy *CastTy = ParseTypeName();
227 SourceLocation RAngleBracketLoc = Tok.getLocation();
228
Chris Lattner1ab3b962008-11-18 07:48:38 +0000229 if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000230 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
Reid Spencer5f016e22007-07-11 17:01:13 +0000231
232 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
233
Chris Lattner1ab3b962008-11-18 07:48:38 +0000234 if (Tok.isNot(tok::l_paren))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000235 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName);
Reid Spencer5f016e22007-07-11 17:01:13 +0000236
Sebastian Redld8c4e152008-12-11 22:33:27 +0000237 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
Reid Spencer5f016e22007-07-11 17:01:13 +0000238
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000239 if (!Result.isInvalid())
Douglas Gregor49badde2008-10-27 19:41:14 +0000240 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
241 LAngleBracketLoc, CastTy, RAngleBracketLoc,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000242 LParenLoc, Result.release(), RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000243
Sebastian Redl20df9b72008-12-11 22:51:44 +0000244 return move(Result);
Reid Spencer5f016e22007-07-11 17:01:13 +0000245}
246
Sebastian Redlc42e1182008-11-11 11:37:55 +0000247/// ParseCXXTypeid - This handles the C++ typeid expression.
248///
249/// postfix-expression: [C++ 5.2p1]
250/// 'typeid' '(' expression ')'
251/// 'typeid' '(' type-id ')'
252///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000253Parser::OwningExprResult Parser::ParseCXXTypeid() {
Sebastian Redlc42e1182008-11-11 11:37:55 +0000254 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
255
256 SourceLocation OpLoc = ConsumeToken();
257 SourceLocation LParenLoc = Tok.getLocation();
258 SourceLocation RParenLoc;
259
260 // typeid expressions are always parenthesized.
261 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
262 "typeid"))
Sebastian Redl20df9b72008-12-11 22:51:44 +0000263 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000264
Sebastian Redl15faa7f2008-12-09 20:22:58 +0000265 OwningExprResult Result(Actions);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000266
267 if (isTypeIdInParens()) {
268 TypeTy *Ty = ParseTypeName();
269
270 // Match the ')'.
271 MatchRHSPunctuation(tok::r_paren, LParenLoc);
272
273 if (!Ty)
Sebastian Redl20df9b72008-12-11 22:51:44 +0000274 return ExprError();
Sebastian Redlc42e1182008-11-11 11:37:55 +0000275
276 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
277 Ty, RParenLoc);
278 } else {
279 Result = ParseExpression();
280
281 // Match the ')'.
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000282 if (Result.isInvalid())
Sebastian Redlc42e1182008-11-11 11:37:55 +0000283 SkipUntil(tok::r_paren);
284 else {
285 MatchRHSPunctuation(tok::r_paren, LParenLoc);
286
287 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000288 Result.release(), RParenLoc);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000289 }
290 }
291
Sebastian Redl20df9b72008-12-11 22:51:44 +0000292 return move(Result);
Sebastian Redlc42e1182008-11-11 11:37:55 +0000293}
294
Reid Spencer5f016e22007-07-11 17:01:13 +0000295/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
296///
297/// boolean-literal: [C++ 2.13.5]
298/// 'true'
299/// 'false'
Sebastian Redl20df9b72008-12-11 22:51:44 +0000300Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
Reid Spencer5f016e22007-07-11 17:01:13 +0000301 tok::TokenKind Kind = Tok.getKind();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000302 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind));
Reid Spencer5f016e22007-07-11 17:01:13 +0000303}
Chris Lattner50dd2892008-02-26 00:51:44 +0000304
305/// ParseThrowExpression - This handles the C++ throw expression.
306///
307/// throw-expression: [C++ 15]
308/// 'throw' assignment-expression[opt]
Sebastian Redl20df9b72008-12-11 22:51:44 +0000309Parser::OwningExprResult Parser::ParseThrowExpression() {
Chris Lattner50dd2892008-02-26 00:51:44 +0000310 assert(Tok.is(tok::kw_throw) && "Not throw!");
Chris Lattner50dd2892008-02-26 00:51:44 +0000311 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000312
Chris Lattner2a2819a2008-04-06 06:02:23 +0000313 // If the current token isn't the start of an assignment-expression,
314 // then the expression is not present. This handles things like:
315 // "C ? throw : (void)42", which is crazy but legal.
316 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
317 case tok::semi:
318 case tok::r_paren:
319 case tok::r_square:
320 case tok::r_brace:
321 case tok::colon:
322 case tok::comma:
Sebastian Redl20df9b72008-12-11 22:51:44 +0000323 return Owned(Actions.ActOnCXXThrow(ThrowLoc));
Chris Lattner50dd2892008-02-26 00:51:44 +0000324
Chris Lattner2a2819a2008-04-06 06:02:23 +0000325 default:
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000326 OwningExprResult Expr(ParseAssignmentExpression());
Sebastian Redl20df9b72008-12-11 22:51:44 +0000327 if (Expr.isInvalid()) return move(Expr);
328 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release()));
Chris Lattner2a2819a2008-04-06 06:02:23 +0000329 }
Chris Lattner50dd2892008-02-26 00:51:44 +0000330}
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000331
332/// ParseCXXThis - This handles the C++ 'this' pointer.
333///
334/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
335/// a non-lvalue expression whose value is the address of the object for which
336/// the function is called.
Sebastian Redl20df9b72008-12-11 22:51:44 +0000337Parser::OwningExprResult Parser::ParseCXXThis() {
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000338 assert(Tok.is(tok::kw_this) && "Not 'this'!");
339 SourceLocation ThisLoc = ConsumeToken();
Sebastian Redl20df9b72008-12-11 22:51:44 +0000340 return Owned(Actions.ActOnCXXThis(ThisLoc));
Argyrios Kyrtzidis4cc18a42008-06-24 22:12:16 +0000341}
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000342
343/// ParseCXXTypeConstructExpression - Parse construction of a specified type.
344/// Can be interpreted either as function-style casting ("int(x)")
345/// or class type construction ("ClassType(x,y,z)")
346/// or creation of a value-initialized type ("int()").
347///
348/// postfix-expression: [C++ 5.2p1]
349/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
350/// typename-specifier '(' expression-list[opt] ')' [TODO]
351///
Sebastian Redl20df9b72008-12-11 22:51:44 +0000352Parser::OwningExprResult
353Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000354 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
355 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val;
356
357 assert(Tok.is(tok::l_paren) && "Expected '('!");
358 SourceLocation LParenLoc = ConsumeParen();
359
Sebastian Redla55e52c2008-11-25 22:21:31 +0000360 ExprVector Exprs(Actions);
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000361 CommaLocsTy CommaLocs;
362
363 if (Tok.isNot(tok::r_paren)) {
364 if (ParseExpressionList(Exprs, CommaLocs)) {
365 SkipUntil(tok::r_paren);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000366 return ExprError();
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000367 }
368 }
369
370 // Match the ')'.
371 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
372
373 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
374 "Unexpected number of commas!");
Sebastian Redl20df9b72008-12-11 22:51:44 +0000375 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
376 LParenLoc,
377 Exprs.take(), Exprs.size(),
378 &CommaLocs[0], RParenLoc));
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000379}
380
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000381/// ParseCXXCondition - if/switch/while/for condition expression.
382///
383/// condition:
384/// expression
385/// type-specifier-seq declarator '=' assignment-expression
386/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
387/// '=' assignment-expression
388///
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000389Parser::OwningExprResult Parser::ParseCXXCondition() {
Argyrios Kyrtzidisa8a45982008-10-05 15:03:47 +0000390 if (!isCXXConditionDeclaration())
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000391 return ParseExpression(); // expression
392
393 SourceLocation StartLoc = Tok.getLocation();
394
395 // type-specifier-seq
396 DeclSpec DS;
397 ParseSpecifierQualifierList(DS);
398
399 // declarator
400 Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
401 ParseDeclarator(DeclaratorInfo);
402
403 // simple-asm-expr[opt]
404 if (Tok.is(tok::kw_asm)) {
Sebastian Redleffa8d12008-12-10 00:02:53 +0000405 OwningExprResult AsmLabel(ParseSimpleAsm());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000406 if (AsmLabel.isInvalid()) {
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000407 SkipUntil(tok::semi);
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000408 return ExprError();
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000409 }
Sebastian Redleffa8d12008-12-10 00:02:53 +0000410 DeclaratorInfo.setAsmLabel(AsmLabel.release());
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000411 }
412
413 // If attributes are present, parse them.
414 if (Tok.is(tok::kw___attribute))
415 DeclaratorInfo.AddAttributes(ParseAttributes());
416
417 // '=' assignment-expression
418 if (Tok.isNot(tok::equal))
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000419 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000420 SourceLocation EqualLoc = ConsumeToken();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000421 OwningExprResult AssignExpr(ParseAssignmentExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000422 if (AssignExpr.isInvalid())
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000423 return ExprError();
424
425 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
426 DeclaratorInfo,EqualLoc,
427 AssignExpr.release()));
Argyrios Kyrtzidis71b914b2008-09-09 20:38:47 +0000428}
429
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000430/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
431/// This should only be called when the current token is known to be part of
432/// simple-type-specifier.
433///
434/// simple-type-specifier:
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000435/// '::'[opt] nested-name-specifier[opt] type-name
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000436/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
437/// char
438/// wchar_t
439/// bool
440/// short
441/// int
442/// long
443/// signed
444/// unsigned
445/// float
446/// double
447/// void
448/// [GNU] typeof-specifier
449/// [C++0x] auto [TODO]
450///
451/// type-name:
452/// class-name
453/// enum-name
454/// typedef-name
455///
456void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
457 DS.SetRangeStart(Tok.getLocation());
458 const char *PrevSpec;
459 SourceLocation Loc = Tok.getLocation();
460
461 switch (Tok.getKind()) {
Chris Lattner55a7cef2009-01-05 00:13:00 +0000462 case tok::identifier: // foo::bar
463 case tok::coloncolon: // ::foo::bar
464 assert(0 && "Annotation token should already be formed!");
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000465 default:
466 assert(0 && "Not a simple-type-specifier token!");
467 abort();
Chris Lattner55a7cef2009-01-05 00:13:00 +0000468
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000469 // type-name
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000470 case tok::annot_qualtypename: {
471 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
472 Tok.getAnnotationValue());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000473 break;
474 }
475
476 // builtin types
477 case tok::kw_short:
478 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
479 break;
480 case tok::kw_long:
481 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
482 break;
483 case tok::kw_signed:
484 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
485 break;
486 case tok::kw_unsigned:
487 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
488 break;
489 case tok::kw_void:
490 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
491 break;
492 case tok::kw_char:
493 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
494 break;
495 case tok::kw_int:
496 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
497 break;
498 case tok::kw_float:
499 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
500 break;
501 case tok::kw_double:
502 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
503 break;
504 case tok::kw_wchar_t:
505 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
506 break;
507 case tok::kw_bool:
508 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
509 break;
510
511 // GNU typeof support.
512 case tok::kw_typeof:
513 ParseTypeofSpecifier(DS);
514 DS.Finish(Diags, PP.getSourceManager(), getLang());
515 return;
516 }
Argyrios Kyrtzidiseb83ecd2008-11-08 16:45:02 +0000517 if (Tok.is(tok::annot_qualtypename))
518 DS.SetRangeEnd(Tok.getAnnotationEndLoc());
519 else
520 DS.SetRangeEnd(Tok.getLocation());
Argyrios Kyrtzidis987a14b2008-08-22 15:38:55 +0000521 ConsumeToken();
522 DS.Finish(Diags, PP.getSourceManager(), getLang());
523}
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000524
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000525/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
526/// [dcl.name]), which is a non-empty sequence of type-specifiers,
527/// e.g., "const short int". Note that the DeclSpec is *not* finished
528/// by parsing the type-specifier-seq, because these sequences are
529/// typically followed by some form of declarator. Returns true and
530/// emits diagnostics if this is not a type-specifier-seq, false
531/// otherwise.
532///
533/// type-specifier-seq: [C++ 8.1]
534/// type-specifier type-specifier-seq[opt]
535///
536bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
537 DS.SetRangeStart(Tok.getLocation());
538 const char *PrevSpec = 0;
539 int isInvalid = 0;
540
541 // Parse one or more of the type specifiers.
542 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
Chris Lattner1ab3b962008-11-18 07:48:38 +0000543 Diag(Tok, diag::err_operator_missing_type_specifier);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000544 return true;
545 }
Daniel Dunbarb90585c2008-11-08 04:28:37 +0000546 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ;
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000547
548 return false;
549}
550
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000551/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000552/// operator name (C++ [over.oper]). If successful, returns the
553/// predefined identifier that corresponds to that overloaded
554/// operator. Otherwise, returns NULL and does not consume any tokens.
555///
556/// operator-function-id: [C++ 13.5]
557/// 'operator' operator
558///
559/// operator: one of
560/// new delete new[] delete[]
561/// + - * / % ^ & | ~
562/// ! = < > += -= *= /= %=
563/// ^= &= |= << >> >>= <<= == !=
564/// <= >= && || ++ -- , ->* ->
565/// () []
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000566OverloadedOperatorKind Parser::TryParseOperatorFunctionId() {
Argyrios Kyrtzidis9057a812008-11-07 15:54:02 +0000567 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000568
569 OverloadedOperatorKind Op = OO_None;
570 switch (NextToken().getKind()) {
571 case tok::kw_new:
572 ConsumeToken(); // 'operator'
573 ConsumeToken(); // 'new'
574 if (Tok.is(tok::l_square)) {
575 ConsumeBracket(); // '['
576 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
577 Op = OO_Array_New;
578 } else {
579 Op = OO_New;
580 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000581 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000582
583 case tok::kw_delete:
584 ConsumeToken(); // 'operator'
585 ConsumeToken(); // 'delete'
586 if (Tok.is(tok::l_square)) {
587 ConsumeBracket(); // '['
588 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
589 Op = OO_Array_Delete;
590 } else {
591 Op = OO_Delete;
592 }
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000593 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000594
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000595#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000596 case tok::Token: Op = OO_##Name; break;
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000597#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000598#include "clang/Basic/OperatorKinds.def"
599
600 case tok::l_paren:
601 ConsumeToken(); // 'operator'
602 ConsumeParen(); // '('
603 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000604 return OO_Call;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000605
606 case tok::l_square:
607 ConsumeToken(); // 'operator'
608 ConsumeBracket(); // '['
609 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']'
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000610 return OO_Subscript;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000611
612 default:
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000613 return OO_None;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000614 }
615
Douglas Gregor43c7bad2008-11-17 16:14:12 +0000616 ConsumeToken(); // 'operator'
617 ConsumeAnyToken(); // the operator itself
Douglas Gregore94ca9e42008-11-18 14:39:36 +0000618 return Op;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000619}
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000620
621/// ParseConversionFunctionId - Parse a C++ conversion-function-id,
622/// which expresses the name of a user-defined conversion operator
623/// (C++ [class.conv.fct]p1). Returns the type that this operator is
624/// specifying a conversion for, or NULL if there was an error.
625///
626/// conversion-function-id: [C++ 12.3.2]
627/// operator conversion-type-id
628///
629/// conversion-type-id:
630/// type-specifier-seq conversion-declarator[opt]
631///
632/// conversion-declarator:
633/// ptr-operator conversion-declarator[opt]
634Parser::TypeTy *Parser::ParseConversionFunctionId() {
635 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
636 ConsumeToken(); // 'operator'
637
638 // Parse the type-specifier-seq.
639 DeclSpec DS;
640 if (ParseCXXTypeSpecifierSeq(DS))
641 return 0;
642
643 // Parse the conversion-declarator, which is merely a sequence of
644 // ptr-operators.
645 Declarator D(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000646 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000647
648 // Finish up the type.
649 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D);
650 if (Result.isInvalid)
651 return 0;
652 else
653 return Result.Val;
654}
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000655
656/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
657/// memory in a typesafe manner and call constructors.
Chris Lattner59232d32009-01-04 21:25:24 +0000658///
659/// This method is called to parse the new expression after the optional :: has
660/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
661/// is its location. Otherwise, "Start" is the location of the 'new' token.
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000662///
663/// new-expression:
664/// '::'[opt] 'new' new-placement[opt] new-type-id
665/// new-initializer[opt]
666/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
667/// new-initializer[opt]
668///
669/// new-placement:
670/// '(' expression-list ')'
671///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000672/// new-type-id:
673/// type-specifier-seq new-declarator[opt]
674///
675/// new-declarator:
676/// ptr-operator new-declarator[opt]
677/// direct-new-declarator
678///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000679/// new-initializer:
680/// '(' expression-list[opt] ')'
681/// [C++0x] braced-init-list [TODO]
682///
Chris Lattner59232d32009-01-04 21:25:24 +0000683Parser::OwningExprResult
684Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
685 assert(Tok.is(tok::kw_new) && "expected 'new' token");
686 ConsumeToken(); // Consume 'new'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000687
688 // A '(' now can be a new-placement or the '(' wrapping the type-id in the
689 // second form of new-expression. It can't be a new-type-id.
690
Sebastian Redla55e52c2008-11-25 22:21:31 +0000691 ExprVector PlacementArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000692 SourceLocation PlacementLParen, PlacementRParen;
693
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000694 bool ParenTypeId;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000695 DeclSpec DS;
696 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000697 if (Tok.is(tok::l_paren)) {
698 // If it turns out to be a placement, we change the type location.
699 PlacementLParen = ConsumeParen();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000700 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
701 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000702 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000703 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000704
705 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000706 if (PlacementRParen.isInvalid()) {
707 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000708 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000709 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000710
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000711 if (PlacementArgs.empty()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000712 // Reset the placement locations. There was no placement.
713 PlacementLParen = PlacementRParen = SourceLocation();
714 ParenTypeId = true;
715 } else {
716 // We still need the type.
717 if (Tok.is(tok::l_paren)) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000718 SourceLocation LParen = ConsumeParen();
719 ParseSpecifierQualifierList(DS);
720 ParseDeclarator(DeclaratorInfo);
721 MatchRHSPunctuation(tok::r_paren, LParen);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000722 ParenTypeId = true;
723 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000724 if (ParseCXXTypeSpecifierSeq(DS))
725 DeclaratorInfo.setInvalidType(true);
726 else
727 ParseDeclaratorInternal(DeclaratorInfo,
728 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000729 ParenTypeId = false;
730 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000731 }
732 } else {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000733 // A new-type-id is a simplified type-id, where essentially the
734 // direct-declarator is replaced by a direct-new-declarator.
735 if (ParseCXXTypeSpecifierSeq(DS))
736 DeclaratorInfo.setInvalidType(true);
737 else
738 ParseDeclaratorInternal(DeclaratorInfo,
739 &Parser::ParseDirectNewDeclarator);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000740 ParenTypeId = false;
741 }
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000742 if (DeclaratorInfo.getInvalidType()) {
743 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000744 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000745 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000746
Sebastian Redla55e52c2008-11-25 22:21:31 +0000747 ExprVector ConstructorArgs(Actions);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000748 SourceLocation ConstructorLParen, ConstructorRParen;
749
750 if (Tok.is(tok::l_paren)) {
751 ConstructorLParen = ConsumeParen();
752 if (Tok.isNot(tok::r_paren)) {
753 CommaLocsTy CommaLocs;
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000754 if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
755 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000756 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000757 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000758 }
759 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000760 if (ConstructorRParen.isInvalid()) {
761 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
Sebastian Redl20df9b72008-12-11 22:51:44 +0000762 return ExprError();
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000763 }
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000764 }
765
Sebastian Redl20df9b72008-12-11 22:51:44 +0000766 return Owned(Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
767 PlacementArgs.take(), PlacementArgs.size(),
768 PlacementRParen, ParenTypeId, DeclaratorInfo,
769 ConstructorLParen, ConstructorArgs.take(),
770 ConstructorArgs.size(), ConstructorRParen));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000771}
772
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000773/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
774/// passed to ParseDeclaratorInternal.
775///
776/// direct-new-declarator:
777/// '[' expression ']'
778/// direct-new-declarator '[' constant-expression ']'
779///
Chris Lattner59232d32009-01-04 21:25:24 +0000780void Parser::ParseDirectNewDeclarator(Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000781 // Parse the array dimensions.
782 bool first = true;
783 while (Tok.is(tok::l_square)) {
784 SourceLocation LLoc = ConsumeBracket();
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000785 OwningExprResult Size(first ? ParseExpression()
786 : ParseConstantExpression());
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000787 if (Size.isInvalid()) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000788 // Recover
789 SkipUntil(tok::r_square);
790 return;
791 }
792 first = false;
793
794 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
Sebastian Redleffa8d12008-12-10 00:02:53 +0000795 Size.release(), LLoc));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000796
797 if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid())
798 return;
799 }
800}
801
802/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
803/// This ambiguity appears in the syntax of the C++ new operator.
804///
805/// new-expression:
806/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
807/// new-initializer[opt]
808///
809/// new-placement:
810/// '(' expression-list ')'
811///
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000812bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
Chris Lattner59232d32009-01-04 21:25:24 +0000813 Declarator &D) {
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000814 // The '(' was already consumed.
815 if (isTypeIdInParens()) {
Sebastian Redlcee63fb2008-12-02 14:43:59 +0000816 ParseSpecifierQualifierList(D.getMutableDeclSpec());
817 ParseDeclarator(D);
818 return D.getInvalidType();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000819 }
820
821 // It's not a type, it has to be an expression list.
822 // Discard the comma locations - ActOnCXXNew has enough parameters.
823 CommaLocsTy CommaLocs;
824 return ParseExpressionList(PlacementArgs, CommaLocs);
825}
826
827/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
828/// to free memory allocated by new.
829///
Chris Lattner59232d32009-01-04 21:25:24 +0000830/// This method is called to parse the 'delete' expression after the optional
831/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
832/// and "Start" is its location. Otherwise, "Start" is the location of the
833/// 'delete' token.
834///
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000835/// delete-expression:
836/// '::'[opt] 'delete' cast-expression
837/// '::'[opt] 'delete' '[' ']' cast-expression
Chris Lattner59232d32009-01-04 21:25:24 +0000838Parser::OwningExprResult
839Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
840 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
841 ConsumeToken(); // Consume 'delete'
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000842
843 // Array delete?
844 bool ArrayDelete = false;
845 if (Tok.is(tok::l_square)) {
846 ArrayDelete = true;
847 SourceLocation LHS = ConsumeBracket();
848 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
849 if (RHS.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000850 return ExprError();
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000851 }
852
Sebastian Redl2f7ece72008-12-11 21:36:32 +0000853 OwningExprResult Operand(ParseCastExpression(false));
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000854 if (Operand.isInvalid())
Sebastian Redl20df9b72008-12-11 22:51:44 +0000855 return move(Operand);
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000856
Sebastian Redl20df9b72008-12-11 22:51:44 +0000857 return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete,
858 Operand.release()));
Sebastian Redl4c5d3202008-11-21 19:14:01 +0000859}